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 }