阿申准备报名参加 GT 考试,准考证号为 nn
位数 X1X2⋯XnX1X2⋯Xn
,他不希望准考证号上出现不吉利的数字。他的不吉利数字 A1A2⋯AmA1A2⋯Am
有 mm
位,不出现是指 X1X2⋯XnX1X2⋯Xn
中没有恰好一段等于 A1A2⋯AmA1A2⋯Am
,A1A1
和 X1X1
可以为 00
。输入格式第一行输入 n,m,Kn,m,K
。接下来一行输入 mm
位的不吉利数字。输出格式阿申想知道不出现不吉利数字的号码有多少种,输出模 KK
取余的结果。数据范围0≤Xi,Ai≤90≤Xi,Ai≤9
,
1≤n≤1091≤n≤109
,
1≤m≤201≤m≤20
,
2≤K≤10002≤K≤1000
输入样例:4 3 100
111
输出样例:81
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 25;
int n, m, mod;
char str[N];
int ne[N];
int a[N][N];
void mul(int c[][N], int a[][N], int b[][N]){
static int t[N][N];
memset(t, 0, sizeof t);
for (int i = 0; i < m ; i ++)
for (int j = 0; j < m ; j ++)
for (int k = 0; k < m; k ++)
t[i][j] = (t[i][j] + a[i][k] * b[k][j]) % mod;
memcpy(c, t, sizeof t);
}
int qmi(int k){
int f0[N][N] = {1};
while(k){
if (k & 1) mul(f0, f0, a);
mul(a, a, a);
k >>= 1;
}
int res = 0;
for (int i = 0; i < m; i ++) res = (res + f0[0][i]) % mod;
return res;
}
int main(){
cin >> n >> m >> mod;
cin >> str + 1;
for (int i = 2, j = 0; i <= m; i ++){
while(j && str[j + 1] != str[i]) j = ne[j];
if (str[j + 1] == str[i]) j ++;
ne[i] = j;
}
for (int j = 0; j < m; j ++)
for (int c = '0'; c <= '9'; c ++){
int k = j;
while(k && str[k + 1] != c) k = ne[k];
if (str[k + 1] == c) k ++;
if (k < m) a[j][k] ++;
}
cout << qmi(n) << endl;
return 0;
}