Luogu P3193 [HNOI2008]GT考试
Link
我们知道往末尾加一个字符就相当于在KMP自动机上走一步,而我们的要求是不能经过终点。
那么矩阵快速幂优化DP即可。
#include<bits/stdc++.h>
using namespace std;
const int M=23,N=5001;
int m,P;
inline int inc(register int a,register int b){return a+b>=P? a+b-P:a+b;}
inline int dec(register int a,register int b){return a<b? a+P-b:a-b;}
struct matrix
{
int a[M][M];
matrix(){memset(a,0,sizeof a);}
inline int *operator[](register int x){return a[x];}
}F,G;
inline matrix operator*(matrix a,matrix b)
{
matrix ans;
for(register int k=0;k<m;++k) for(register int i=0;i<m;++i) for(register int j=0;j<m;++j) ans[i][j]=inc(ans[i][j],a[i][k]*b[k][j]%P);
return ans;
}
inline matrix power(matrix a,register int k)
{
matrix ans;
for(register int i=0;i<=m;++i) ans[i][i]=1;
for(;k;k>>=1,a=a*a) if(k&1) ans=a*ans;
return ans;
}
int Next[N],match[N][50];
char Mode[N];
int main()
{
register int n,ans=0;cin>>n>>m>>P;scanf("%s",Mode+1);
Next[0]=-1;
for(register int i=1,j;i<=m;++i)
{
j=Next[i-1];
while(j!=-1&&Mode[j+1]!=Mode[i]) j=Next[j];
Next[i]=j+1;
}
Next[0]=0;
for(register int i=0,j,tmp;i<m;++i)
for(j='0';j<='9';++j)
{
tmp=i;
while(Mode[tmp+1]!=j&&tmp>0) tmp=Next[tmp];
if(Mode[tmp+1]==j) ++tmp;
if(tmp<m) ++match[i][tmp];
}
F[0][0]=1;
for(register int i=0;i<=m;++i) for(register int j=0;j<=m;++j) G[i][j]=match[i][j];
G=power(G,n),F=F*G;
for(register int i=0;i<m;++i)ans=inc(ans,F[0][i]);
return cout<<ans,0;
}