zoukankan      html  css  js  c++  java
  • [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;
    }
    
    
  • 相关阅读:
    搜索存储过程中的关键字
    替换回车换行
    js 常用正则表达式
    获取存储过程返回值
    DataReader 转datatable
    文件打包下载
    My97DatePicker设置当天之后的日期不可选变灰色
    嵌套类引用实例化的外部类的方法
    可叠加定义的成员变量的赋值及操作(权限)
    Java中List中remove的实质
  • 原文地址:https://www.cnblogs.com/mollnn/p/13255074.html
Copyright © 2011-2022 走看看