[HNOI2008] GT考试

Description

准考证号为 (N) 位数 (X_1,X_2…X_n(0le X_ile9)),他不希望准考证号上出现不吉利的数字。他的不吉利数 (A_1,A_2…A_m(0le A_ile 9))(M) 位,不出现是指 (X_1,X_2…X_n) 中没有恰好一段等于 (A_1,A_2…A_m)(A_1)(X_1) 可以为 (0)

Solution

(next[i]) 表示 (A[1..i]) 的最长公共真前后缀,可以 KMP 预处理出

构造矩阵,当匹配到 (i) 位置 (+c) 可以转移到 (p) 位置时,对 (mat[p][i]++)

这就是 DP 的转移矩阵,快速幂处理即可

(实际上最后我们只需要统计幂矩阵的第一列的和)

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 25;

int n,m,mod;
char s[N];

namespace kmp
{
    char *p=s;
    int n,m,fail[N];
    void main()
    {
        m=strlen(p+1);
        for(int i=2; i<=m; i++)
        {
            fail[i]=fail[i-1];
            while(p[fail[i]+1]-p[i] && fail[i]) fail[i]=fail[fail[i]];
            if(p[fail[i]+1]==p[i]) ++fail[i];
        }
        fail[0]=-1;
    }
}

struct matrix
{
    int n,a[N][N];

    matrix(int n=0):n(n)
    {
        memset(a,0,sizeof a);
    }

    int* operator [] (int i)
    {
        return a[i];
    }

    friend matrix operator * (matrix a,matrix b)
    {
        int n=a.n;
        matrix res(n);
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                for(int k=1; k<=n; k++)
                {
                    res[i][k]=((res[i][k]+a[i][j]*b[j][k])%mod+mod)%mod;
                }
            }
        }
        return res;
    }

    matrix I()
    {
        matrix res(n);
        for(int i=1; i<=n; i++)
        {
            res[i][i]=1;
        }
        return res;
    }

    matrix operator ^ (int b)
    {
        if(b) return (((*this)*(*this))^(b/2))*(b&1?(*this):I());
        return I();
    }

    void print()
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++) cout<<a[i][j]<<"	";
            cout<<endl;
        }
    }
};

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m>>mod>>s+1;
    kmp::main();

    matrix mat(m);
    using kmp::fail;
    for(int i=0;i<m;i++)
    {
        for(char c='0';c<='9';c++)
        {
            int p=i;
            while(p && s[p+1]!=c) p=fail[p];
            if(s[p+1]==c) ++p;
            ++mat[p+1][i+1];
        }
    }
    //mat.print();
    mat=mat^n;
    //mat.print();
    int ans=0;
    for(int i=1;i<=m;i++) ans=(ans+mat[i][1])%mod;
    cout<<ans<<endl;
}

原文地址:https://www.cnblogs.com/mollnn/p/13255074.html