[不稳定的传送门

Solution

dp[i][j]表示前i个字符当前匹配到不吉利串的第j个,即当前方案的后缀等于不吉利串前缀

然而由于n过大,不能直接转移,用矩阵优化

Code

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std; char s[120];
int n,m,mo,nex[120]; inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
} struct info{
int n,m,A[30][30];
info(int a,int b):n(a),m(b){memset(A,0,sizeof(A));}
int *operator [](int x){return A[x];}
friend info operator *(info a,info b){
info c(a.n,b.m);
for(int i=0;i<c.n;++i)
for(int j=0;j<c.m;++j)
for(int k=0;k<a.m;++k)
c[i][j]=(c[i][j]+1ll*a[i][k]*b[k][j]%mo)%mo;
return c;
}
}; info Pow(info A,int c){
info res(A.n,A.m);
for(int i=0;i<res.n;++i) res[i][i]=1;
for(;c;c>>=1,A=A*A) if(c&1) res=res*A;
return res;
} void Init(){
n=read(),m=read(),mo=read();
scanf("%s",s+1);
for(int i=2,j=0;i<=m;++i){
while(j&&s[i]!=s[j+1]) j=nex[j];
if(s[i]==s[j+1]) ++j;
nex[i]=j;
}
} void solve(){
info a(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=nex[k];
if(s[k+1]==j) k++;
if(k!=m) a[i][k]++;
}
info Ans(1,m),tmp=Pow(a,n);
Ans[0][0]=1;
Ans=Ans*tmp;
int sum=0;
for(int i=0;i<m;++i)
(sum+=Ans[0][i])%=mo;
printf("%d\n",sum);
} int main(){Init();solve();return 0;}
05-23 01:52