[HihoCoder1259]A Math Problem

题目大意:
  有一个函数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 }

 

posted @ 2017-10-27 12:05  skylee03  阅读(107)  评论(0编辑  收藏  举报