题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3329
解法:x xor 2x=3x(与x xor 3x=2x等价)求满足等式且小于n的x的个数,与满足等式小于2n的数的个数。因为异或是不
进位的二进制加法,那么因为结果正好和加法相同,那么说明x在二进制上没有相邻的1。那么简单的数位DP就可以求出
满足这个的答案了。 在第一问的基础上打表可以发现答案恰好就是fib数列的第2项,所以我们矩阵快速幂搞一下。
///BZOJ 3329
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
LL dp[100][2];
LL n, digit[100];
LL dfs(int pos, int val, int jud){
if(pos==0) return 1;
if(!jud&&dp[pos][val]!=-1) return dp[pos][val];
int up=jud?digit[pos]:1;
LL ans=0;
for(int i=0; i<=up; i++){
if(!val||!i){
ans += dfs(pos-1,i,jud&&i==up);
}
}
if(!jud) dp[pos][val]=ans;
return ans;
}
LL f(LL x){
int pos=0;
while(x){
digit[++pos]=x&1;
x/=2;
}
return dfs(pos,0,1);
}
struct Matrix{
LL a[2][2];
void init(){
for(int i=0; i<2; i++){
for(int j=0; j<2; j++){
a[i][j]=0;
}
}
}
};
Matrix operator *(Matrix a, Matrix b){
Matrix res;
res.init();
for(int i=0; i<2; i++){
for(int j=0; j<2; j++){
for(int k=0; k<2; k++){
res.a[i][j]=(res.a[i][j]+a.a[i][k]*b.a[k][j])%mod ;
}
}
}
return res;
}
Matrix powmod(Matrix a, LL n){
Matrix res;
res.init();
for(int i=0; i<2; i++) res.a[i][i]=1;
while(n){
if(n&1LL) res=res*a;
a=a*a;
n>>=1LL;
}
return res;
}
int main(){
memset(dp, -1, sizeof(dp));
int T;
scanf("%d", &T);
while(T--){
scanf("%lld", &n);
LL ans1 = f(n)-1;
Matrix A, B;
A.a[0][0]=A.a[0][1]=A.a[1][0]=1;A.a[1][1]=0;
B.a[0][0]=1;B.a[1][0]=0;
A=powmod(A,n+1);
A=A*B;
LL ans2=A.a[0][0];
printf("%lld\n%lld\n", ans1, ans2);
}
return 0;
}