题意
给定一个字符串,求定长的不包含这个字符串的字符串数量。
思路
设子状态(dp[i][j])表示求的字符串匹配到i,给定的字符串最多匹配到j的答案数量,那么所求即为(sum dp[n][i]),转移用kmp维护。
但是这样速度还是不过,观察之后考虑矩阵快速幂。
代码
#include <bits/stdc++.h>
using namespace std;
namespace StandardIO {
template<typename T> inline void read (T &x) {
x=0;T f=1;char c=getchar();
for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
x*=f;
}
template<typename T> inline void write (T x) {
if (x<0) putchar('-');
if (x>=10) write(x/10);
putchar(x%10+'0');
}
}
using namespace StandardIO;
namespace Solve {
const int N=22;
int n,m,k;
char s[N];
int next[N];
int dp[N][N];
struct Matrix {
int ans[N][N];
}base;
inline Matrix operator * (Matrix a,Matrix b) {
Matrix c;
for (register int i=0; i<m; ++i) {
for (register int j=0; j<m; ++j) {
c.ans[i][j]=0;
for (register int K=0; K<m; ++K) {
c.ans[i][j]=(c.ans[i][j]+1ll*a.ans[i][K]*b.ans[K][j]%k)%k;
}
}
}
return c;
}
inline Matrix operator ^ (Matrix a,int p) {
Matrix res=a;--p;
while (p) {
if (p&1) res=res*a;
a=a*a,p>>=1;
}
return res;
}
inline int insert (char c,int j) {
while (j&&s[j+1]!=c) j=next[j];
if (s[j+1]==c) ++j;
return j;
}
inline void MAIN () {
read(n),read(m),read(k),scanf("%s",s+1);
for (register int i=2,j=0; i<=m; ++i) {
while (j&&s[j+1]!=s[i]) j=next[j];
if (s[j+1]==s[i]) ++j;
next[i]=j;
}
for (register int i=0; i<m; ++i) {
for (register char c='0'; c<='9'; ++c) {
int K=insert(c,i);
++base.ans[i][K];
}
}
Matrix ans=base^n;int res=0;
for (register int i=0; i<m; ++i) {
res=(res+ans.ans[0][i])%k;
}
write(res);
}
}
int main () {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
Solve::MAIN();
}