一看还以为要搞一个类似于数位dp的东西,然后还想不出来,一点没往别处想还是我太弱了。。。

我们把这题的过程看成字符串的匹配,那就是求匹配到最后还没匹配上的情况有多少种,我们可以考虑kmp的过程来dp计数;

dp[i][j]=sum(dp[i-1][k]*cnt[k][j])(j,k<m),dp[i][j]表示到了s串的第i个字符和t串匹配了j个的情况,cnt[k][j]表示由原来匹配了k个后移一个字符之后变成j个的情况数,可以由kmp数组预处理出来,我们可以把cnt数组看成一个矩阵CNT,把每个dp[i]看成一个矩阵DPi,则

DPn=DPn-1*CNT;

DPn=DP0*CNT^n;

矩阵快速幂

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,mod;
struct matr{
    int t[25][25];
    matr operator*(matr &a){
        matr c;
        for(int i=0;i<m;++i)
            for(int j=0;j<m;++j){
                c.t[i][j]=0;
                for(int k=0;k<m;++k)
                c.t[i][j]=(c.t[i][j]+t[i][k]*a.t[k][j]%mod)%mod;
            }
        return c;
    }
}A,ans;
char s[25];
int ne[25];
void pre(){
    for(int i=2,j=0;i<=m;++i){
        while(s[j+1]!=s[i]&&j>0)j=ne[j];
        if(s[j+1]==s[i])++j;ne[i]=j;
    }
}
int main(){
    cin>>n>>m>>mod;
    scanf("%s",s+1);
    pre();
    for(int i=0;i<m;++i)
      for(int j=0;j<=9;++j){
        int p=i;
        while(p>0&&s[p+1]-'0'!=j)p=ne[p];
        if(s[p+1]-'0'==j)++p;
        if(p!=m)A.t[i][p]=(A.t[i][p]+1)%mod;
    }
    for(int i=0;i<m;++i)ans.t[i][i]=1;
    while(n){
        if(n&1)ans=ans*A;
        n>>=1;A=A*A;
    }
    int sum=0;
    for(int i=0;i<m;++i)
    sum=(sum+ans.t[0][i])%mod;
    cout<<sum<<endl;
    system("pause");
    return 0;
}

 

posted on 2018-01-17 12:07  湮灭之瞳  阅读(324)  评论(0编辑  收藏  举报