[BZOJ1009]GT考试
首先想到dp的状态f[i][j],当前处理到第i位,并有末尾j位是与原串匹配上的
转移就应该是f[i][j]=sigma(f[i-1][k],k->匹配到第k位,能加上一位使得匹配长度变成j位);也可以写成f[i][j]=sigma(f[i-1][k]*a[k][j]),其中a[k][j]表示能使匹配长度从k变成j的末位数的个数
比如,对于123124来说f[i][3]=f[i-1][2]*a[2][3]+f[i-1][5]*a[5][3],即******12加上一位3或***12312加上一位3使匹配长度变成3
a数组是可以用KMP预处理出来的,枚举第二维长度和最后一位的取值,通过KMP找到第一维,把该点的a值加1
然后矩阵优化
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxm 25 4 int n,m,mod,pi[maxm]; 5 char str[maxm]; 6 struct Mat{ 7 int a[maxm][maxm]; 8 void clear(){ 9 memset(a,0,sizeof(a)); 10 } 11 void operator=(const Mat &t){ 12 for(int i=0;i<m;i++) 13 for(int j=0;j<m;j++) 14 a[i][j]=t.a[i][j]; 15 } 16 Mat operator*(const Mat &t)const{ 17 Mat tmp; 18 for(int i=0;i<m;i++) 19 for(int j=0;j<m;j++){ 20 tmp.a[i][j]=0; 21 for(int k=0;k<m;k++) 22 tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*t.a[k][j])%mod; 23 } 24 return tmp; 25 } 26 }; 27 int main(){ 28 scanf("%d%d%d",&n,&m,&mod); 29 scanf("%s",str+1); 30 int k=-1; 31 pi[0]=-1; 32 for(int i=1;i<=m;i++){ 33 while(k>=0&&str[k+1]!=str[i])k=pi[k]; 34 pi[i]=++k; 35 } 36 Mat A;A.clear(); 37 for(int i=0;i<m;i++) 38 for(int j=0;j<=9;j++){ 39 k=i; 40 while(k>=0&&str[k+1]-'0'!=j)k=pi[k]; 41 if(++k!=m)A.a[k][i]=(A.a[k][i]+1)%mod; 42 } 43 Mat ans;ans.clear(); 44 for(int i=0;i<m;i++)ans.a[i][i]=1; 45 while(n){ 46 if(n&1)ans=ans*A; 47 A=A*A; 48 n>>=1; 49 } 50 int haha=0; 51 for(int i=0;i<m;i++) 52 haha=(haha+ans.a[i][0])%mod; 53 printf("%d\n",haha); 54 return 0; 55 }