Description
Seeking the number of length n, 0-9 digit string does not contain a numeric string given length m.
Solution
dp on kmp automaton
40pts kmp + dp
Consider \ (DP \) , provided \ (f_ {i, j} \) representing the forward (I \) \ characters given to the first matching string to \ (J \) Program Number of bits
A character at what to put Enumeration transfer, then \ (KMP \) process where the match will be one, and the \ (f_ {i, j} \) was transferred to \ (f_ {i, nxt} \ ) . It should be noted that, if the match to the next bit is \ (m \) , then no transfer.
The final answer is \ (\ SUM \ limits_ I = {0} ^ {m}. 1-F [n-] [I] \) .
Code
#include <bits/stdc++.h>
using namespace std;
const int _ = 20 + 10;
const int __ = 1e6 + 10;
int N, M, mod, nxt[_];
char s[_];
int f[__][_];
inline void kmp() {
nxt[1] = 0;
for (int i = 2, j = 0; i <= M; ++i) {
while (j > 0 && s[i] != s[j + 1]) j = nxt[j];
if (s[i] == s[j + 1]) ++j;
nxt[i] = j;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("GT.in", "r", stdin);
freopen("GT.out", "w", stdout);
#endif
scanf("%d%d%d", &N, &M, &mod);
scanf("%s", s + 1);
kmp();
f[0][0] = 1;
for (int i = 0; i < N; ++i) {
for (int j = 0; j <= M; ++j) {
for (int k = 0; k <= 9; ++k) {
int tmp = j;
while (tmp > 0 && k != s[tmp + 1] - '0') tmp = nxt[tmp];
if (k == s[tmp + 1] - '0') ++tmp;
if (tmp < M) f[i + 1][tmp] = (f[i + 1][tmp] + f[i][j]) % mod;
}
}
}
int ans = 0;
for (int i = 0; i < M; ++i) ans = (ans + f[N][i]) % mod;
printf("%d\n", ans);
return 0;
}
100pts accelerate the transfer matrix
In fact, does not need to enumerate each letter, we can pre-program another number into the match length from a length plus a matching character set \ (g_ {i, j} \)
Then
\ [f_ {i, j}
= \ sum \ limits_ {k = 0} ^ {m-1} f_ {i-1, k} \ times g_ {k, j} \] This matrix equation can be clearly optimization, so after a quick power matrix, can, through this question of.
Code
#include <bits/stdc++.h>
using namespace std;
const int _ = 23;
int N, M, mod, nxt[_], cnt[_][_];
char s[_];
struct Matrix {
int A[_][_];
Matrix() { memset(A, 0, sizeof(A)); }
Matrix operator*(const Matrix &b) const {
Matrix c;
memset(c.A, 0, sizeof(c.A));
for (int i = 0; i < M; ++i)
for (int j = 0; j < M; ++j)
for (int k = 0; k < M; ++k)
c.A[i][j] = (c.A[i][j] + A[i][k] * b.A[k][j] % mod) % mod;
return c;
}
} F, G;
inline void kmp() {
nxt[1] = 0;
for (int i = 2, j = 0; i <= M; ++i) {
while (j > 0 && s[i] != s[j + 1]) j = nxt[j];
if (s[i] == s[j + 1]) ++j;
nxt[i] = j;
}
for (int i = 0; i < M; ++i) {
for (int j = '0'; j <= '9'; ++j) {
int k = i;
while (k > 0 && j != s[k + 1]) k = nxt[k];
if (j == s[k + 1]) ++k;
if (k < M) ++cnt[i][k];
}
}
}
Matrix ksm(Matrix a, int b) {
Matrix ret;
for (int i = 0; i < M; ++i) ret.A[i][i] = 1;
for (; b; b >>= 1) {
if (b & 1) ret = ret * a;
a = a * a;
}
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("GT.in", "r", stdin);
freopen("GT.out", "w", stdout);
#endif
scanf("%d%d%d", &N, &M, &mod);
scanf("%s", s + 1);
kmp();
for (int i = 0; i < M; ++i)
for (int j = 0; j < M; ++j) G.A[i][j] = cnt[i][j];
F.A[0][0] = 1;
G = ksm(G, N);
F = F * G;
int ans = 0;
for (int i = 0; i < M; ++i) ans = (ans + F.A[0][i]) % mod;
printf("%d\n", ans);
return 0;
}