[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

输入

第一行输入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;
}

 

posted @ 2016-08-11 17:33  xjr01  阅读(252)  评论(0编辑  收藏  举报