Los Garden Valley P1357

Original title link

answer

First, consider the $ N \ leq 10 ^ 5 $

It is easy to think of dynamic programming

We can easily state design

$ F_ {i, j} $ represents the number of programs

$ I $ has been determined that the current position $ i $

J represents $ $ $ j-m + 1 ~ j $ binary states

And state transition equation

$ F_ {i, j} = \ Sigma {f_ {i-1, k}} (k, j k are legitimate and the access is the one J) $

So we just need to pre-whether all states can convert between various legal and state, and then to dynamic programming

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int MOD=1e9+7,MAXN=1e5+50,MAXM=8,MAXP=70;
 5 inline void add(int &x,int y){
 6     x=(x+y)%MOD;
 7 }
 8 LL N;
 9 int M,K;
10 bool bin[MAXM],leg[MAXP]/*״̬ÊÇ·ñºÏ·¨*/,tran[MAXP][MAXP]/*תÒÆÊÇ·ñºÏ·¨*/;
11 inline void sign(){
12     int cur=0,nxt=0,sum[MAXM]={0};
13     for(int i=1;i<=M;i++)
14         cur=cur<<1|bin[i];
15     for(int i=2;i<=M+1;i++)
16         nxt=nxt<<1|bin[i];
17     for(int i=1;i<=M+1;i++)
18         sum[i]=sum[i-1]+bin[i];
19     if(sum[M]>K||sum[M+1]-sum[1]>K)
20         return;
21     leg[cur]=leg[nxt]=1;
22     tran[cur][nxt]=1;
23 }
24 void dfs(int x){/*ö¾Ù²¢±ê¼ÇËùÓкϷ¨µÄ״̬*/
25     if(x==M+2){
26         sign();
27         return;
28     }
29     bin[x]=0;
30     dfs(x+1);
31     bin[x]=1;
32     dfs(x+1);
33 }
34 int f[MAXN][MAXP],maxp,ans;
35 inline void dp(int S){/*Çó½â´ÓÌض¨×´Ì¬³ö·¢µÄ·½°¸Êý*/
36     memset(f,0,sizeof(f));
37     f[M][S]=1;
38     for(int i=M+1;i<=M+N;i++)
39         for(int j=0;j<maxp;j++)
40             for(int k=0;k<maxp;k++)
41                 if(tran[j][k])/*´æÔÚjµ½kµÄתÒÆ*/
42                     add(f[i][j],f[i-1][k]);
43     add(ans,f[N+M][S]);
44 }
45 int main(){
46     scanf("%lld%d%d",&N,&M,&K);
47     dfs(1);
48     maxp=1<<M;
49     for(int i=0;i<maxp;i++)
50         if(leg[i])
51             dp(i);
52     printf("%d",ans);
53     return 0;
54 }
View Code

 

Then consider $ N \ leq 10 ^ {15} $

We observed that pretreatment of the adjacency matrix (whether each state transition between the matrix), can be found which is actually a transfer problem closure (similar to the Floyd), each state will be pressing the matrix operation N times

It is possible to use fast power optimization matrix, the code is very simple

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int MOD=1e9+7,MAXN=1e5+50,MAXM=8,MAXP=70;
 5 inline void add(LL &x,LL y){
 6     x=(x+y)%MOD;
 7 }
 8 LL N,maxp,ans,M,K;
 9 bool bin[MAXM],leg[MAXP];
10 struct matrix{
11     LL a[MAXP][MAXP];
12     matrix (){
13         memset(a,0,sizeof(a));
14     }
15     friend matrix operator*(matrix x,matrix y){
16         matrix ret;
17         for(int i=0;i<maxp;i++)
18             for(int j=0;j<maxp;j++)
19                 for(int k=0;k<maxp;k++)
20                     add(ret.a[i][j],x.a[i][k]*y.a[k][j]);
21         return ret;
22     }
23 }tran,a;
24 inline void sign(){
25     int cur=0,nxt=0,sum[MAXM]={0};
26     for(int i=1;i<=M;i++)
27         cur=cur<<1|bin[i];
28     for(int i=2;i<=M+1;i++)
29         nxt=nxt<<1|bin[i];
30     for(int i=1;i<=M+1;i++)
31         sum[i]=sum[i-1]+bin[i];
32     if(sum[M]>K||sum[M+1]-sum[1]>K)
33         return;
34     leg[cur]=leg[nxt]=1;
35     tran.a[cur][nxt]=1;
36 }
37 void dfs(int x){
38     if(x==M+2){
39         sign();
40         return;
41     }
42     bin[x]=0;
43     dfs(x+1);
44     bin[x]=1;
45     dfs(x+1);
46 }
47 inline matrix pow(matrix x,LL y){
48     matrix ret=x;
49     y--;
50     while(y){
51         if(y&1){
52                 ret=ret*x;
53         }
54         x=x*x;
55         y>>=1;
56     }
57     return ret;
58 }
59 int main(){
60     scanf("%lld%lld%lld",&N,&M,&K);
61     maxp=1<<M;
62     dfs(1);
63     a=pow(tran,N);
64     for(int i=0;i<maxp;i++)
65         if(leg[i])
66             add(ans,a.a[i][i]);
67     printf("%lld",ans);
68      return  0 ;
69 }
View Code

 

 

Guess you like

Origin www.cnblogs.com/guoshaoyang/p/11139346.html