[BZOJ1009][HNOI2008]GT考试
[BZOJ1009][HNOI2008]GT考试
试题描述
阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。
他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0
他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0
输入
第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000
输出
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.
输入示例
4 3 100 111
输出示例
81
数据规模及约定
见“输入”
题解
设计 dp,f(i, j) 表示考号前 i 位匹配到不吉利串第 j 位的方案数,考虑在 f(i, j) 这个状态下,在后面添加一位,那么有可能转到 f(i+1, j+1) 或 f(i+1, k),那么我们可以暴力求出这个 k,构造一下转移矩阵,快速幂一下就好了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
#define maxn 25
int n, m, MOD;
struct Matrix {
int n, m, A[maxn][maxn];
Matrix() { n = m = 0; memset(A, 0, sizeof(A)); }
Matrix operator * (const Matrix& t) const {
Matrix ans; ans.n = t.n; ans.m = m;
for(int i = 0; i <= ans.n; i++)
for(int j = 0; j <= ans.m; j++) {
ans.A[i][j] = 0;
for(int k = 0; k <= n; k++) {
ans.A[i][j] += (A[k][j] * t.A[i][k]) % MOD;
if(ans.A[i][j] >= MOD) ans.A[i][j] -= MOD;
}
}
return ans;
}
Matrix operator *= (const Matrix& t) {
*this = *this * t;
return *this;
}
} b, t;
char S[maxn], tmp[maxn];
Matrix Pow(Matrix a, int b) {
Matrix ans = a, t = a; b--;
while(b) {
if(b & 1) ans *= t;
t *= t; b >>= 1;
}
return ans;
}
int main() {
n = read(); m = read(); MOD = read();
scanf("%s", S + 1);
for(int i = 1; i <= m; i++) S[i] -= '0';
for(int st = 0; st < m; st++) {
int cnt = 0;
for(int i = 1; i <= st; i++) tmp[++cnt] = S[i];
for(int x = 0; x <= 9; x++) {
tmp[++cnt] = x;
bool has = 0;
for(int j = 1; j <= cnt; j++) {
bool ok = 1;
int k, i;
for(k = j, i = 1; k <= cnt; k++, i++) if(tmp[k] != S[i]) {
ok = 0; break;
}
if(ok) {
has = 1;
t.A[i-1][st]++;
break;
}
}
if(!has) t.A[0][st]++;
cnt--;
}
}
b.A[0][0] = 1;
b.n = m; b.m = 0;
t.n = t.m = m;
// printf("\\ "); for(int i = 0; i <= t.n; i++) printf("%d ", i); putchar('\n');
// for(int i = 0; i <= t.n; i++) {
// printf("%d ", i);
// for(int j = 0; j <= t.m; j++) printf("%d ", t.A[i][j]);
// putchar('\n');
// }
b *= Pow(t, n);
int ans = 0;
for(int i = 0; i < m; i++) {
ans += b.A[i][0];
if(ans >= MOD) ans -= MOD;
}
printf("%d\n", ans);
return 0;
}

浙公网安备 33010602011771号