[BZOJ3329]Xorequ(数位DP+矩阵快速幂)

好题好题!(又被模数坑了(大雾。。。))

首先第一问我就死了,把式子全搞到了一边,然后发现那个乘3的非常难做,于是打表找规律。

可以很显然地发现:第二问是个fibonacci数列,很激动,但并没有什么卵用,没有部分分这个题。

第一问其实是化为了问有多少个数在二进制下没有相邻的1,这样就可以用数位DP做了。

dfs记录处理到第几位,上一个是什么,是否受限,是否为最高位,很套路(注意不要取模,那个是第二问的)

  1 //第一问没有相邻的1?
  2 //第二问fibonacci(n+2)项?
  3 #include<iostream>
  4 #include<cstdio>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<vector>
  9 #include<string>
 10 #include<cstring>
 11 #include<map>
 12 #define int long long
 13 #define max(a,b) (a>b?a:b)
 14 #define min(a,b) (a>b?b:a)
 15 #define m(a) memset(a,0,sizeof(a))
 16 #define AA cout<<"Alita"<<endl
 17 using namespace std;
 18 const int mod=1e9+7;
 19 int n,len,T,ans1,ans2,f[65][15][2][2];
 20 struct Ma{int f[5][5];}A,B,S;
 21 int dfs(int x,int y,int z,int k)
 22 {
 23         if(!x) return 1;
 24         if(f[x][y][z][k]!=-1) return f[x][y][z][k];
 25         f[x][y][z][k]=0;
 26         if(k)
 27         {
 28                 f[x][y][z][k]+=dfs(x-1,1,0,0);
 29                 f[x][y][z][k]+=dfs(x-1,0,0,1);
 30                 return f[x][y][z][k];
 31         }
 32         if(z)
 33         {
 34                 if(n&(1ll<<(x-1)))
 35                 {
 36                         if(!y) f[x][y][z][k]+=dfs(x-1,1,1,0);
 37                         f[x][y][z][k]+=dfs(x-1,0,0,0);
 38                 }
 39                 else
 40                 {
 41                         f[x][y][z][k]+=dfs(x-1,0,1,0);
 42                 }
 43         }
 44         else
 45         {
 46                 if(!y) f[x][y][z][k]+=dfs(x-1,1,0,0);
 47                 f[x][y][z][k]+=dfs(x-1,0,0,0);
 48         }
 49         return f[x][y][z][k];
 50 }
 51 Ma X(Ma x,Ma y)
 52 {
 53         Ma ans;m(ans.f);
 54         for(int i=1;i<=2;i++)
 55         {
 56                 for(int j=1;j<=2;j++)
 57                 {
 58                         for(int k=1;k<=2;k++)
 59                         {
 60                                 (ans.f[i][j]+=x.f[i][k]*y.f[k][j]%mod)%=mod;
 61                         }
 62                 }
 63         }
 64         return ans;
 65 }
 66 int FI(int x)
 67 {
 68         m(A.f);m(B.f);m(S.f);
 69         A.f[1][1]=0;A.f[1][2]=1;
 70         A.f[2][1]=1;A.f[2][2]=1;
 71         B.f[1][1]=0;B.f[2][1]=1;
 72         S.f[1][1]=1;S.f[2][2]=1;
 73         while(x)
 74         {
 75                 if(x&1) S=X(S,A);
 76                 x>>=1;
 77                 A=X(A,A);
 78         }
 79         B=X(S,B);
 80         return B.f[2][1];
 81 }
 82 void work()
 83 {
 84         memset(f,-1,sizeof(f));
 85         len=0;
 86         scanf("%lld",&n);
 87         int tmp=n;
 88         while(tmp)
 89         {
 90                 len++;
 91                 tmp>>=1;
 92         }
 93         ans1=dfs(len-1,1,1,0)+dfs(len-1,0,0,1)-1;
 94         ans2=FI(n+1);
 95         printf("%lld\n%lld\n",ans1,ans2);
 96 }
 97 signed main()
 98 {
 99         //freopen("1.in","r",stdin);
100         //freopen("1.out","w",stdout);
101         scanf("%lld",&T);
102         while(T--) work();
103         return 0;
104 }

 

posted @ 2019-08-06 21:45  ATHOSD  阅读(81)  评论(0编辑  收藏  举报