[BZOJ1009][HNOI2008]GT考试:KMP+矩阵加速DP

分析:

有点像一道叫牛继电器的题(233)。
不过矩阵构造要用到KMP。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,k,nxt[25];
char s[25];
struct Matrix{
    int a[25][25];
    Matrix(){
        memset(a,0,sizeof a);
    }
    friend Matrix operator * (Matrix lf,Matrix rt){
        Matrix ans;
        for(int i=0;i<m;i++)
            for(int j=0;j<m;j++)
                for(int l=0;l<m;l++)
                    ans.a[i][j]=(ans.a[i][j]+lf.a[i][l]*rt.a[l][j])%k;
        return ans;
    }
}ID,PR;
Matrix Mpow(Matrix x,int y){
    Matrix ans=ID,t=x;
    while(y){
        if(y&1) ans=ans*t;
        t=t*t;
        y>>=1;
    }
    return ans;
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<m;i++)
        ID.a[i][i]=1;
    scanf("%s",s+1);
    for(int i=2,j=0;i<=m;i++){
        while(j&&s[i]!=s[j+1]) j=nxt[j];
        if(s[i]==s[j+1]) j++;
        nxt[i]=j;
    }
    for(int i=0;i<m;i++){
        for(char j='0';j<='9';j++){
            int t=i;
            while(t&&s[t+1]!=j) t=nxt[t];
            if(s[t+1]==j) t++;
            if(t!=m) PR.a[i][t]=(PR.a[i][t]+1)%k;
        }
    }
    Matrix ans=Mpow(PR,n);
    int sum=0;
    for(int i=0;i<m;i++)
        sum=(sum+ans.a[0][i])%k;
    printf("%d\n",sum);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9387853.html