首页 > 其他 > 详细

[HNOI2008]GT考试

时间:2020-01-21 13:53:44      阅读:48      评论:0      收藏:0      [点我收藏+]

题目链接:Click here

Solution:

考虑dp,\(f[i][j]\)表示已经确定了\(i\)位,当前匹配到第\(j\)位的方案数

给出的字符串是固定,不难发现我们每次转移的方程也是一个与上次状态无关的固定的东西
\[ f[i][j]=\sum_{k=0} ^{m-1} f[i-1][k]\times g[k][j] \]
显而易见的是,这是一个矩乘的模式,而转移矩阵\(g\)我们可以通过\(kmp\)很快的求出来

那么我们矩乘优化dp即可,时间复杂度\(O(m^3 \lg n)\)

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M=21;
int n,m,mod,ans,nxt[M];
char s[M];
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
struct Matrix{
    int l,r,a[M][M];
    void init(int L,int R){
        l=L;r=R;
        memset(a,0,sizeof(a));
    }
    void IE(){for(int i=0;i<M;i++)a[i][i]=1;}
    friend Matrix operator *(Matrix u,Matrix v){
        Matrix t;t.init(u.l,v.r);
        for(int i=0;i<u.l;i++)
            for(int j=0;j<v.r;j++)
                for(int k=0;k<u.r;k++)
                    t.a[i][j]=(t.a[i][j]+(u.a[i][k]*v.a[k][j]%mod))%mod;
        return t;
    }
};
Matrix qpow(Matrix a,int b){
    Matrix re;re.init(m,m);re.IE();
    while(b){
        if(b&1) re=re*a;
        b>>=1;a=a*a;
    }return re;
}
Matrix kmp(){
    for(int i=2,j=0;i<=m;i++){
        while(j&&s[j+1]!=s[i]) j=nxt[j];
        if(s[j+1]==s[i]) ++j;
        nxt[i]=j;
    }
    Matrix tmp;tmp.init(m,m);
    for(int i=0;i<m;i++)
        for(char j='0';j<='9';j++){
            int k=i;
            while(k&&s[k+1]!=j) k=nxt[k];
            if(s[k+1]==j) ++k;
            ++tmp.a[i][k];
        }
    return tmp;
}
signed main(){
    n=read(),m=read(),mod=read();
    scanf("%s",s+1);
    Matrix trans;trans=kmp();
    trans=qpow(trans,n);
    for(int i=0;i<m;i++) ans=(ans+trans.a[0][i])%mod;
    printf("%lld\n",ans);
    return 0;
}

[HNOI2008]GT考试

原文:https://www.cnblogs.com/NLDQY/p/12221286.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!