1. 程式人生 > >bzoj1009 GT考試 (kmp+矩陣優化dp)

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 }