BZOJ3329 Xorequ(数位dp+矩阵快速幂)
根据题意x^2x=3x
异或和普通加法的关系其实就是异或是不进位加法,我们把3x看作x+2x
这样其实求的就是异或中x和2x每一位异或都是0的答案,也就是x中没有相邻1,因为2x就是x左移而来
对于第二问,一看数据范围就知道是个数学规律题,因为普通做法不可做,观察可得,这是斐波那契数列的n+2项,因此使用矩阵快速幂
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=4e5+10; const int mod=1e9+7; int s[N]; ll n; int cnt=0; ll f[70][2][2]; struct node{ ll a[3][3]; void init(){ memset(a,0,sizeof a); } }S,T; node operator *(node a,node b){ int i,j,k; node tmp; tmp.init(); for(i=1;i<=2;i++){ for(j=1;j<=2;j++){ for(k=1;k<=2;k++){ tmp.a[i][j]=(tmp.a[i][j]+a.a[i][k]*b.a[k][j])%mod; } } } return tmp; } node qpow(node a,ll k){ node c; c.init(); c.a[1][1]=c.a[2][2]=1; while(k){ if(k&1){ c=c*a; } a=a*a; k>>=1; } return c; } ll get(ll n){ S.init(); T.init(); S.a[1][1]=1,S.a[2][1]=1; T.a[1][1]=T.a[1][2]=T.a[2][1]=1; T=qpow(T,n); S=S*T; return S.a[1][1]; } ll dfs(int u,int sign,int last){ if(u==0) return 1; auto &x=f[u][sign][last]; if(x!=-1) return x; int up=1; if(sign){ up=s[u]; } int i; ll res=0; for(i=0;i<=up;i++){ if(i){ if(last==0) res+=dfs(u-1,sign&&(i==up),1); } else{ res+=dfs(u-1,sign&&(i==up),0); } } return x=res; } ll solve(ll x){ memset(f,-1,sizeof f); cnt=0; while(x){ s[++cnt]=(x&1); x>>=1; } return dfs(cnt,1,0)-1; } int main(){ ios::sync_with_stdio(false); int i; int t; cin>>t; while(t--){ cin>>n; cout<<solve(n)<<endl; cout<<get(n+1)<<endl; } }
没有人不辛苦,只有人不喊疼