【BZOJ】1009GT考试-kmpDP

传送门:bzoj1009


题解

先用kmp预处理一下dp的转移状态。
然后矩阵快速幂一波?(这个矩阵快速幂比较妙妙,我都没想到)


代码

#include<bits/stdc++.h>
using namespace std;
int n,m,mod,nxt[25];
struct mat{
    int t[25][25];
}a,b,c,tmp;
char s[25];
int sum;
inline void mul(mat &A,mat &B,mat &C)
{
    int i,j,k;
    for(i=0;i<m;i++){
        for(j=0;j<m;j++){
            tmp.t[i][j]=0;
            for(k=0;k<m;k++){
                tmp.t[i][j]=(tmp.t[i][j]+A.t[i][k]*B.t[k][j])%mod;
            }
        }
    }
    for(i=0;i<m;i++)
    for(j=0;j<m;j++) C.t[i][j]=tmp.t[i][j];
}

int main(){
    scanf("%d%d%d",&n,&m,&mod);
    scanf("%s",s+1);
    int now=0;
    for(int i=2;i<=m;i++){
        while(now && s[now+1]!=s[i]) now=nxt[now];
        nxt[i]=s[now+1]==s[i]?++now:0;
    }
    for(int tp,i=0;i<m;i++){
        for(int j=0;j<=9;j++){
            tp=i;
            while(tp && (int)s[tp+1]!=j+48 ) {
              tp=nxt[tp];
            }
            tp+= (int)s[tp+1]==j+48? 1: 0;
            if(tp!=m) b.t[tp][i]=(b.t[tp][i]+1)%mod;
        }
    }
    for(int i=0;i<m;i++) a.t[i][i]=1;
    while(n){
        if(n&1) mul(a,b,a);
        mul(b,b,b);
        n>>=1;
    }
    for(int i=0;i<m;i++) 
      sum=(sum+a.t[i][0])%mod;
    printf("%d\n",sum);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/80517461