zoukankan      html  css  js  c++  java
  • bzoj 1009: [HNOI2008]GT考试【kmp+dp+矩阵快速幂】

    看n和k的范围长得就很像矩阵乘法了
    设f[i][j]表示到第i个位置的后缀最长匹配目标串的j位。转移的话显然是枚举0~9,然后选择f[i+1]中能被他转移的加起来,需要用到next数组。然后构造矩阵的时候,在转移路径上++即可(注意代码里的f数组只是辅助构造矩阵的,和上文无关
    在写挂了n次kmp之后我突然意识到一个问题:k<=20,我随便暴力个5、6次方的都没问题为啥要kmp……
    结果还是用了kmp

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int M=30;
    int n,m,mod,c[M],ne[M],f[M][M],an;
    char s[M];
    struct qwe
    {
        int a[M][M];
        void init()
        {
            memset(a,0,sizeof(a));
        }
        qwe operator * (const qwe &b) const
        {
            qwe c;
            c.init();
            for(int k=0;k<m;k++)
                for(int i=0;i<m;i++)
                    for(int j=0;j<m;j++)
                        c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%mod;
            return c;
        }
    }a,sum;
    void getne()
    {
        // int i=0,j=-1;
        // ne[0]=-1;
        // while(i<m)
        // {
            // if(c[i]==c[j]||j==-1)
                // ne[++i]=++j;
            // else
                // j=ne[j];
        // }
        for(int i=1;i<m;i++)
        {
            int j=ne[i];
            while(j&&c[i+1]!=c[j+1]) 
                j=ne[j];
            ne[i+1]=c[i+1]==c[j+1]?j+1:0;
        }   
    }
    qwe ksm(int b)
    {
        qwe r;
        r.init();
        for(int i=0;i<m;i++)
            r.a[i][i]=1;
        while(b)
        {
            if(b&1)
                r=r*a;
            a=a*a;
            b>>=1;
        }
        return r;
    }
    int main()
    {
        scanf("%d%d%d%s",&n,&m,&mod,s+1);
        for(int i=1;i<=m;i++)
            c[i]=s[i]-'0';
        getne();
        for(int i=0;i<m;i++) 
            for(int j=0;j<=9;j++)
            {
                f[i][j]=c[i+1]==j?i+1:f[ne[i]][j];
                a.a[i][f[i][j]]++;
            }
        sum.a[0][0]=1;
        sum=sum*ksm(n);
        for(int i=0;i<m;i++)
            an=(an+sum.a[0][i])%mod;
        printf("%d
    ",an);
        return 0;
    }
    
  • 相关阅读:
    模拟title提示!
    常用CSS缩写语法总结
    cron表达式每个月最后一天,corn表达式使用L报错
    浏览器调试器(F12)详解
    查询重复数据只显示一条并且在规定范围时间内
    java导出统计数据excel设置单元格样式
    微信小程序官方人脸核身认证
    小程序引用app.js中的全局变量
    微信小程序 view中的image水平垂直居中
    MYSQL中的sql_mode模式
  • 原文地址:https://www.cnblogs.com/lokiii/p/8604358.html
Copyright © 2011-2022 走看看