标签:cal 进制 span ems 函数 思路 接下来 etc git
题目大意:
有一个函数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 }
标签:cal 进制 span ems 函数 思路 接下来 etc git
原文地址:http://www.cnblogs.com/skylee03/p/7742539.html