一看还以为要搞一个类似于数位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; }