题意:
给定字符串ch,问长度为n的字符串,有多少种可能不包含字符串ch
思路:
算是比较经典的dp的题,我们首先容易想到包含这个串的字符串有多少个,但是发现难以实现,
然后我们用递推的方式来直接求解不包含这个串的新串的个数,
令dp[i][j] 表示 我们维护的当前串长度为 i,并且其包含j个字符的后缀 恰好是ch串的前缀,
那么答案ans即为 ans += dp[n][i] : i in range(0, m-1);
这样,对于第 i+1 个字符(可以是'0'~'9')有10种转移方式,即转移到dp[i+1][x]:x即新的匹配到的位置;这里需要用到kmp以快速得到x (关于往下一个符号匹配也可以看这个括号匹配的题 https://blog.csdn.net/xiang_6/article/details/81505075)
如果已经匹配完了ch串,那我们不对这个串继续往后转移,也就不会对答案做出贡献;
但是因为 n 很大,我们还得推得:dp[i][0],dp[i][1]...dp[i][m-1] 与 dp[i+1][0],dp[i+1][1]...dp[i+1][m-1] 之间的关系;也就是矩阵快速幂的转移方程,
如代码:我们令b[t][i] 表示已经匹配完ch串中的i个字符后,有多少种方法使得下一个匹配完成的是第t个字符
经过快速幂运算后 a[][] 原数组中:a[0][0], a[1][0]...a[m-1][0] 表示的是 dp[n][0],dp[n][1]...dp[n][m-1]
/**************************************************************
Problem: 1009
User: xiang_6
Language: C++
Result: Accepted
Time:96 ms
Memory:1292 kb
****************************************************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m, mod;
int p[27];
char ch[27];
int a[27][27], b[27][27];
void mul(int a[27][27], int b[27][27], int ans[27][27]) {
int tmp[27][27];
for(int i = 0; i < m; ++i) {
for(int j = 0; j < m; ++j) {
tmp[i][j] = 0;
for(int k = 0; k < m; ++k) {
tmp[i][j] = (tmp[i][j] + a[i][k]*b[k][j]) % mod;
}
}
}
for(int i = 0; i < m; ++i) {
for(int j = 0; j < m; ++j) {
ans[i][j] = tmp[i][j];
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &mod);
scanf("%s", ch+1);
p[1] = 1, p[2] = 1;
for(int i = 2; i < m; ++i) {
int j = p[i];
while(j>1 && ch[j]!=ch[i]) j = p[j];
p[i+1] = (ch[i] == ch[j] ? j+1 : 1);
}
for(int i = 0; i < m; ++i) {
for(int j = 0; j <= 9; ++j) {
int t = i+1;
while(t > 1 && ch[t]-'0' != j) t = p[t];
if(ch[t]-'0' != j) t--;
if(t != m) b[t][i] = (b[t][i]+1)%mod;
}
}
for(int i = 0; i < m; ++i) {
a[i][i] = 1;
}
while(n) {
if(n&1) mul(a,b,a);
mul(b,b,b);
n >>= 1;
}
int ans = 0;
for(int i = 0; i < m; ++i) {
ans = (ans + a[i][0]) % mod;
}
printf("%d\n", ans);
return 0;
}
/*
.::::.
.::::::::.
::::::::::: I want to say...Accepted!
..:::::::::::'
'::::::::::::'
.::::::::::
'::::::::::::::..
..::::::::::::.
``:::::::::::::::·
::::``:::::::::' .:::.
::::' ':::::' .::::::::.
.::::' :::: .:::::::'::::.
.:::' ::::: .:::::::::' ':::::.
.::' :::::.:::::::::' ':::::.
.::' ::::::::::::::' ``::::.
...::: ::::::::::::' ``::.
```` ':. ':::::::::' ::::..
'.:::::' ':'````..
******************** 美↑女坐键↓盘 ********************
┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐
│Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ ┌┐ ┌┐ ┌┐
└───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘ └┘ └┘ └┘
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐
│~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │
├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤
│ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │
├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │
│ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │
├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤
│ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │
├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││
│ Ctrl│ │Alt │ Space │ Alt│ │ │Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│
└─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘
*/