Description
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; }