[bzoj3329]Xorque

首先将问题转化为2x^x=3x,那么相当于让x右移一位和原数的1不相交,即不含有相邻的1,第一个问题可以直接数位dp,第二个问题可以类似dp+矩乘优化即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define mod 1000000007
 5 struct ji{
 6     int a[2][2];
 7     ji operator * (const ji &b){
 8         ji c;
 9         for(int i=0;i<2;i++)
10             for(int j=0;j<2;j++)
11                 c.a[i][j]=(1LL*a[i][0]*b.a[0][j]+1LL*a[i][1]*b.a[1][j])%mod;
12         return c;
13     }
14 }p;
15 int t,ans,a[101];
16 ll n,f[101][2];
17 ll dfs(int k,int t,int p){
18     if (!k)return 1;
19     if ((p)&&(f[k][t]))return f[k][t];
20     int ma=1;
21     ll ans=0;
22     if (!p)ma=a[k]; 
23     for(int i=0;i<=ma;i++)
24         if ((!i)||(!t))ans+=dfs(k-1,i,p|(i<ma));
25     if (p)f[k][t]=ans;
26     return ans; 
27 }
28 ll calc(ll k){
29     a[0]=0;
30     memset(f,0,sizeof(f));
31     while (k){
32         a[++a[0]]=k%2;
33         k/=2;
34     }
35     return dfs(a[0],0,0); 
36 }
37 ji ksm(ji n,ll m){
38     if (m==1)return n;
39     ji s=ksm(n,m>>1);
40     s=s*s;
41     if (m&1)s=s*n;
42     return s;
43 }
44 int main(){
45     scanf("%d",&t);
46     while (t--){
47         scanf("%lld",&n);
48         printf("%lld\n",calc(n)-1);
49         if (n==1){
50             printf("2\n");
51             continue;
52         }
53         p=ksm(ji{1,1,1,0},n-1);
54         ans=0;
55         for(int i=0;i<2;i++)
56             for(int j=0;j<2;j++)ans=(ans+p.a[i][j])%mod;
57         printf("%d\n",ans);
58     }
59 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11323966.html