bzoj3329: Xorequ
首先画下柿子
x^(2x+x)=2x
假如x能够把括号里的x消掉,那么2x+x是不能在进位的,而2x是x<<1啊,所以满足条件的x没有相邻两位同时是1
遂数位DP解决,对于第二个问矩乘加速
第n次1LL<<i没打LL见祖宗
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9+7; LL f[110][2]; void solve1(LL n) { int p=0;LL k=n; while(k>0)p++,k/=2; LL ans=0; for(int i=p;i>=1;i--) if(n&(1LL<<i-1)) { ans+=f[i][0]; if(n&(1LL<<i)){ans--;break;} } ans++; printf("%lld\n",ans-1); } struct Matrix { LL mp[4][4]; Matrix(){memset(mp,0,sizeof(mp));} friend Matrix operator *(Matrix a,Matrix b) { Matrix c; for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) for(int k=1;k<=2;k++) c.mp[i][j]=(c.mp[i][j]+a.mp[i][k]*b.mp[k][j])%mod; return c; } }; void solve2(LL n) { Matrix ans,A;n--; ans.mp[1][1]=1,ans.mp[1][2]=1; A.mp[1][1]=1,A.mp[1][2]=1,A.mp[2][1]=1; while(n!=0) { if(n%2==1)ans=ans*A; A=A*A;n/=2; } printf("%lld\n",(ans.mp[1][1]+ans.mp[1][2])%mod); } int main() { f[1][0]=1,f[1][1]=1; for(int i=2;i<=62;i++) f[i][0]=f[i-1][0]+f[i-1][1], f[i][1]=f[i-1][0]; int T; scanf("%d",&T); while(T--) { LL n; scanf("%lld",&n); solve1(n); solve2(n); } return 0; }
pain and happy in the cruel world.