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;
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12222002.html