题目大意:给定方程
x xor 3x=2x
,给定正整数n
(1)求小于等于
n
的正整数中有多少个满足该方程
(2)求小于等于
题解:性质:
a xor b=c⇔a xor c=b
把
x xor 3x=2x
变成
x xor 2x=3x
由于异或本质上是不进位加法,有性质
a
&
2x
相当于
x<<1
,条件最后变成
x
的二进制位上没有相邻的
第一问直接数位dp
第二问:设
g(i)
表示
i
位的满足条件的
按二进制位易知
g(i)=g(i−1)+g(i−2)
,同时有
g(0)=0,g(1)=1
把 ≤2n 拆分成 2n 一个数和所有二进制小于等于 n 位的数
用一下fib的求和公式即可
log
求解
我的收获:2333
#include <bits/stdc++.h>
using namespace std;
#define rep(i,x) for(int i=0;i<x;i++)
const int N=2;
const int P=1e9+7;
int T;
int bit[66];
long long n,f[66][2];
struct Matrix{
int x,y;long long v[N][N];
long long *operator [] (int x){return v[x];}
Matrix(int _x,int _y,int w=0){
x=_x,y=_y;
rep(i,N) rep(j,N) v[i][j]=(i==j)?w:0;
}
};
Matrix operator * (Matrix a,Matrix b){
Matrix c(a.x,b.y);
rep(i,a.x) rep(j,b.y) rep(k,a.y) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%P;
return c;
}
Matrix operator ^ (Matrix a,long long b){
Matrix c(a.x,a.y,1);
for(;b;b>>=1,a=a*a)
if(b&1) c=c*a;
return c;
}
Matrix A(N,N),B(1,N);
long long dfs(int x,int s,int e)
{
if(!x) return 1;
if(!e&&f[x][s]!=-1) return f[x][s];
long long ret=0;int u=e?bit[x]:1;
for(int i=0;i<=u;i++){
if(s&&i) continue;
ret+=dfs(x-1,i,e&&i==u);
}
return !e?f[x][s]=ret:ret;
}
long long calc(long long x)
{
int len=0;memset(f,-1,sizeof(f));
while(x) bit[++len]=x%2,x/=2;
return dfs(len,0,1);
}
void MakeMatrix()
{
A[0][0]=A[0][1]=A[1][0]=1;
A[1][1]=0;
B[0][1]=0,B[0][0]=1;
}
void fib()
{
MakeMatrix();
A=A^(n+1);A=A*B;
printf("%lld\n%lld\n",calc(n)-1 ,A[0][0]);
}
void work()
{
cin>>n;
fib();
}
int main()
{
cin>>T;
while(T--) work();
return 0;
}