HNOI2008GT考试

题目链接

考虑dp,f(i,j)表示做到了第i位(共n位),当前的后缀串与A1~Aj相匹配 接下来的方案数。转移的话枚举一个k=0~9表示这位选什么,如果选了以后,匹配的位置会改变到 j' ,j'可以通过预处理A串的next数组(就是kmp里面的那个)然后不断向前跳得到,所以f(i,j) = ∑ f(i+1, j')。

发现转移系数与i无关,因此可以用next数组处理出系数矩阵(长宽均为m),再做矩阵快速幂即可。

复杂度O(m^3*logn)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#define P puts("lala")
#define cp cerr<<"lala"<<endl
#define ln putchar('
')
#define pb push_back
#define fi first
#define se second 
#define mkp make_pair
using namespace std;
inline int read()
{
    char ch=getchar();int g=1,re=0;
    while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
    while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
    return re*g;
}
typedef long long ll;
typedef pair<int,int> pii;

const int M=25;
struct mat
{
    int n,m;
    int s[M][M];
    mat() {clean();}
    void clean() {memset(s,0,sizeof(s));n=m=0;}
};
int mod;

mat operator * (mat a,mat b)
{
    mat c;
    c.n=a.n; c.m=b.m;
    for(int i=0;i<a.n;++i) for(int j=0;j<b.m;++j) for(int k=0;k<a.m;++k)
        c.s[i][j]=(c.s[i][j]+a.s[i][k]*b.s[k][j]%mod)%mod;
    return c;
}
mat fpm(mat a,int n)
{
    mat ans;
    ans.n=ans.m=a.n;
    for(int i=0;i<a.n;++i) ans.s[i][i]=1;
    for(;n;n>>=1,a=a*a) if(n&1) ans=ans*a;
    return ans;
}

mat X,V;
char s[M];
int n,m,next[M];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);freopen("1.out","w",stdout);
#endif
    int i,j,opt,T;
    n=read();m=read();mod=read();
    scanf("%s",s+1);
    next[1]=0;
    int k=0;
    for(i=2;i<=m;++i)
    {
        while(k>0&&s[k+1]!=s[i]) k=next[k];
        if(s[k+1]==s[i]) k++;
        next[i]=k;
    }
    for(i=0;i<m;++i)
    {
        for(j=0;j<10;++j)
        {
            int k=i;
            while(k>0&&j!=s[k+1]-48) k=next[k];
            if(j==s[k+1]-48) k++;
            if(k<m) X.s[i][k]=(X.s[i][k]+1)%mod;
        }
    }
    X.n=X.m=m;
    V.n=m; V.m=1;
    for(i=0;i<m;++i) V.s[i][0]=1;
    X=fpm(X,n);
    X=X*V;
    printf("%d
",X.s[0][0]%mod);
    return 0;
}
/*

*/
原文地址:https://www.cnblogs.com/thkkk/p/7994884.html