BZOJ3329 Xorequ(数位dp+矩阵快速幂)
显然当x中没有相邻的1时该式成立,看起来这也是必要的。
于是对于第一问,数位dp即可。第二问写出dp式子后发现就是斐波拉契数列,矩阵快速幂即可。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define P 1000000007 #define ll long long int T,num[100]; ll n,dp[100][2][2]; struct matrix { int n,a[2][2]; matrix operator *(const matrix&b) const { matrix c;c.n=n;memset(c.a,0,sizeof(c.a)); for (register int i=0;i<n;i++) for (register int j=0;j<2;j++) for (register int k=0;k<2;k++) c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j]%P)%P; return c; } }f,a; ll solve1(ll n) { memset(dp,0,sizeof(dp)); int m=-1; while (n) num[++m]=n&1,n>>=1; dp[m+1][0][1]=1; for (int i=m;~i;i--) if (num[i]) { dp[i][0][0]=dp[i+1][0][0]+dp[i+1][0][1]+dp[i+1][1][0]+dp[i+1][1][1]; dp[i][1][0]=dp[i+1][0][0]; dp[i][1][1]=dp[i+1][0][1]; } else { dp[i][0][0]=dp[i+1][0][0]+dp[i+1][1][0]; dp[i][0][1]=dp[i+1][0][1]+dp[i+1][1][1]; dp[i][1][0]=dp[i+1][0][0]; } return dp[0][0][0]+dp[0][0][1]+dp[0][1][0]+dp[0][1][1]; } int solve2(ll n) { a.n=2;a.a[0][0]=0;a.a[0][1]=a.a[1][0]=a.a[1][1]=1; f.n=1;f.a[0][0]=0,f.a[0][1]=1; for (;n;n>>=1,a=a*a) if (n&1) f=f*a; return f.a[0][1]; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj3329.in","r",stdin); freopen("bzoj3329.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif T=read(); while (T--) { scanf(LL,&n); printf(LL,solve1(n)-1); printf("%d\n",solve2(n+1)); } return 0; }