bzoj3329 Xorequ

Description

bzoj3329 Xorequ_第1张图片

Input

第一行一个正整数,表示数据组数据 ,接下来T行 每行一个正整数N

Output

2*T行 第2*i-1行表示第i个数据中问题一的解,

第2*i行表示第i个数据中问题二的解,

x xor 3x == 2x

可化为x xor 2x == 3x

由a+b == (a xor b)+(a and b)<<1,得

x and 2x == 0

所以x的二进制表示中没有相邻的1

第一问数位dp即可

第二问状态转移方程为f[i]=f[i-1]+f[i-2],可用矩阵快速幂优化

#include<cstdio>
#define P 1000000007
typedef long long lint;
int t;
lint x;
lint fs[64]={1,2};
lint ps[64][2][2]={0,1,1,1};
void f(lint x){
    lint ans=0;
    for(lint i=61;i>=0;i--){
        if(x>>i&1){
            if(x>>i+1&1){
                ans+=fs[i]-1;
                break;
            }else ans+=fs[i];
        }
    }
    lint m[2][2]={0,1,1,1},m1[2][2]={0,0,0,0};
    for(lint i=0;i<62;i++){
        if(x>>i&1){
            for(int a=0;a<2;a++)
            for(int b=0;b<2;b++)
            for(int c=0;c<2;c++){
                m1[a][b]+=m[a][c]*ps[i][c][b];
                m1[a][b]%=P;
            }
        for(int a=0;a<2;a++)
        for(int b=0;b<2;b++)
            m[a][b]=m1[a][b],m1[a][b]=0;
        }
    }
    printf("%lld\n%lld\n",ans,m[1][1]);
}
int main(){
    for(int i=2;i<64;i++)fs[i]=fs[i-1]+fs[i-2];
    for(int i=1;i<64;i++){
        for(int a=0;a<2;a++)
        for(int b=0;b<2;b++)
        for(int c=0;c<2;c++){
            ps[i][a][b]+=ps[i-1][a][c]*ps[i-1][c][b];
            ps[i][a][b]%=P;
        }
    }
    scanf("%d",&t);
    while(t--){
        scanf("%lld",&x);
        f(x);
    }
    return 0;
}

 

你可能感兴趣的:(bzoj3329 Xorequ)