\(f[i][j]\)表示當前擺放到第\(i\)位,而後當前的匹配長度爲\(j\)c++
\(g[i][j]\)表示將長度爲\(i\)的匹配變成長度爲\(j\)的匹配的方案數。這個能夠kmp預處理出來:枚舉當前已匹配長度\(i\)和當前要放的下一個字符,跳一下\(nxt\)看能匹配的長度,每次對\(g[i][j]+1\)便可。這樣是\(O(10\times m^2)\)
而後這個式子矩陣快速冪優化一下便可。
總複雜度是\(O(10\times m^2+m^3\log n)\)優化
/* $f[i][j]$表示當前擺放到第$i$位,而後當前的匹配長度爲$j$ * $f[i][j]=\sum {f[i][k]*g[k][j]}$ $g[i][j]$表示加一個字符將長度爲$i$的匹配變成長度爲$j$的匹配的方案數。這個能夠kmp預處理出來。 */ #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 25; inline void read(int &x) { x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } x *= f; } int n, m, mod, nxt[N]; char a[N]; struct mat { int c[21][21]; mat() {memset(c, 0, sizeof(c));} mat operator * (mat &x) { mat ans; for(int i = 0; i < m; ++i) for(int j = 0; j < m; ++j) for(int k = 0; k < m; ++k) (ans.c[i][j] += c[i][k] * x.c[k][j] % mod) %= mod; return ans; } }A; int main() { #ifndef ONLINE_JUDGE freopen("data.in","r",stdin); #endif read(n); read(m); read(mod); scanf("%s", a + 1); memset(nxt, 0, sizeof(nxt)); for(int i = 2, j = 0; i <= m; ++i) { while(j && a[j + 1] != a[i]) j = nxt[j]; if(a[j + 1] == a[i]) ++j; nxt[i] = j; } for(int i = 0; i < m; ++i) { for(int j = '0'; j <= '9'; ++j) { int tmp = i; while(tmp && a[tmp + 1] != j) tmp = nxt[tmp]; if(a[tmp + 1] == j) ++tmp; if(tmp != m) ++A.c[i][tmp]; } } mat ans; ans.c[0][0] = 1; while(n) { if(n & 1) ans = ans * A; A = A * A; n >>= 1; } int Ans = 0; for(int i = 0; i < m; ++i) (Ans += ans.c[0][i]) %= mod; printf("%d\n", Ans); return 0; }