bzoj1009 GT考试 (kmp+矩阵优化dp)

设f[i][j]是到第i位 已经匹配上了j位的状态数 然后通过枚举下一位放0~9,可以用kmp处理出一个转移的矩阵

然后就可以矩阵快速幂了

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxm=22;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 int N,M,K,trans[maxm][maxm],ans[maxm][maxm],tmp[maxm][maxm],fail[maxm];
16 char x[maxm];
17 
18 inline void mul(int a[][maxm],int b[][maxm]){
19     for(int i=0;i<M;i++){
20         for(int j=0;j<M;j++){
21             tmp[i][j]=0;
22             for(int k=0;k<M;k++){
23                 tmp[i][j]+=a[i][k]*b[k][j],tmp[i][j]%=K;
24             }
25         }
26     }
27 }
28 
29 inline void modp(int b){
30     while(b){
31         if(b&1) mul(ans,trans),memcpy(ans,tmp,sizeof(ans));
32         mul(trans,trans),memcpy(trans,tmp,sizeof(tmp));
33         b>>=1;
34     }
35 }
36 
37 int main(){
38     //freopen("","r",stdin);
39     int i,j,k;
40     N=rd(),M=rd(),K=rd();
41     scanf("%s",x+1);
42     for(i=2,j=0;i<=M;i++){
43         while(j&&x[i]!=x[j+1]) j=fail[j];
44         if(x[i]==x[j+1]) j++;
45         fail[i]=j;
46     }
47     for(i=0;i<M;i++){
48         for(j='0';j<='9';j++){
49             int k=i;
50             while(k&&j!=x[k+1]) k=fail[k];
51             if(j==x[k+1]) k++;
52             if(k<M) trans[i][k]++;
53         }
54     }
55     ans[0][0]=9,ans[0][1]=1;
56     modp(N-1);
57     int p=0;
58     for(i=0;i<M;i++) p+=ans[0][i];
59     printf("%d\n",p%K);
60     return 0;
61 }

 

posted @ 2018-11-01 08:40  Ressed  阅读(162)  评论(0编辑  收藏  举报