1. 程式人生 > >[HihoCoder1259]A Math Problem

[HihoCoder1259]A Math Problem

ons line reg i++ std coder pan 進制 type

題目大意:
  有一個函數f(n),滿足3f(n)*f(2n+1)=f(2n)*(1+3f(n)),f(2n)<6f(n)。
  我們用g(t)表示f(i)%k=t的i的個數,其中1<=i<=n。
  問對於0<=x<k,所有的g(x)的異或和。

思路:
  將函數用遞推式表示為:
  f(2n)=3f(n)
  f(2n+1)=f(2n)+1
  也就是說f(n)就是將n的二進制數串當作一個三進制數來算的值。
  接下來就是一個簡單的數位DP。
  f[i][j]表示DP到第i位,前面那麽多數所構成的三進制的值在模k意義下的值。

 1
#include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 typedef long long int64; 5 inline int64 getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int64 x=ch^0; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^
0); 10 return x; 11 } 12 const int K=65537; 13 inline int log2(const float &x) { 14 return ((unsigned&)x>>23&255)-127; 15 } 16 int64 f[2][K]; 17 inline int64 calc(const int64 &n,const int &k) { 18 int sum=0; 19 const int len=log2(n); 20 memset(f[len&1
],0,sizeof *f); 21 for(register int i=len;i>=0;i--) { 22 memset(f[!(i&1)],0,sizeof *f); 23 const int cur=n>>i&1; 24 sum=(sum*3)%k; 25 for(register int j=0;j<cur;j++) { 26 f[i&1][(sum+j)%k]++; 27 } 28 sum=(sum+cur)%k; 29 for(register int j=0;j<k;j++) { 30 f[!(i&1)][j*3%k]+=f[i&1][j]; 31 f[!(i&1)][(j*3+1)%k]+=f[i&1][j]; 32 } 33 } 34 f[0][0]--; 35 f[0][sum]++; 36 int64 ans=0; 37 for(register int i=0;i<k;i++) { 38 ans^=f[0][i]; 39 } 40 return ans; 41 } 42 int main() { 43 for(register int T=getint();T;T--) { 44 int64 n=getint(); 45 int k=getint(); 46 printf("%lld\n",calc(n,k)); 47 } 48 return 0; 49 }

[HihoCoder1259]A Math Problem