BZOJ1009 GT考试

1009: [HNOI2008]GT考试

Time Limit: 1 Sec  Memory Limit: 162 MB

Description

  阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。
他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0

Input

第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000

Output

阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.

Sample Input

4 3 100
111

Sample Output

81

水题
用KMP求出转移矩阵(不反对暴力)
直接矩阵快速幂

/* Stay hungry, stay foolish. */
#include<iostream>
#include<algorithm>
#include<queue>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<sstream>
#include<stack>
#include<ctime>
#include<cmath>
#include<cctype>
#include<climits>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<iomanip>
#include<bitset>
#include<complex>
using namespace std;
/*
#define getchar() getc()
char buf[1<<15],*fs,*ft;
inline char getc()  {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin)),fs==ft)?0:*fs++;}
*/
template <class _T> inline void read(_T &_x) {
	int _t; bool _flag=false;
	while((_t=getchar())!='-'&&(_t<'0'||_t>'9')) ;
	if(_t=='-') _flag=true,_t=getchar(); _x=_t-'0';
	while((_t=getchar())>='0'&&_t<='9') _x=_x*10+_t-'0';
	if(_flag) _x=-_x;
}
typedef long long LL;
const int maxm = 30;
int n, m, mod;
struct Matrix {
	int v[maxm][maxm], n, m;
	Matrix() {memset(v, 0, sizeof v); }
	Matrix(int a, int b):n(a), m(b) {memset(v, 0, sizeof v); }
	void init() {for (int i = 0; i <= n && i <= m; ++i) v[i][i] = 1; }
	Matrix operator * (Matrix B)const {
		Matrix C(n, B.m);
		for (int i = 0; i <= n; ++i)
			for (int j = 0; j <= B.m; ++j)
				for (int k = 0; k <= m; ++k)
					(C.v[i][j] += v[i][k] * B.v[k][j]) %= mod;
		return C;
	}
	Matrix operator ^ (int t) {
		Matrix ans(n, m), x = *this;
		ans.init();
		for ( ; t; t >>= 1, x = x * x)
			if (t & 1) ans = ans * x;
		return ans;
	}
	inline void print() {
		for (int i = 0; i <= n; ++i) {
			for (int j = 0; j <= m; ++j) {
				printf("%d ", v[i][j]);
			}
			puts("");
		}
	}
};
int nxt[maxm];
int main() {
	//freopen("test.in","r",stdin);
	//freopen(".out","w",stdout);
	read(n), read(m), read(mod);
	char s[maxm];
	scanf("%s", s + 1);
	nxt[1] = 0;
	for (int i = 2, j; i <= m; ++i) {
		j = nxt[i - 1];
		while (j && s[j + 1] != s[i]) j = nxt[j];
		if (s[j + 1] == s[i]) ++j;
		nxt[i] = j;
	}
	Matrix x(m, m);
	for (int i = 0; i < m; ++i) {
		for (int j = 0, k; j <= 9; ++j) {
			k = i;
			while (k && s[k + 1] - '0' != j) k = nxt[k];
			if (s[k + 1] - '0' == j) ++k;
			if (k != m) (++x.v[k][i]) %= mod;
		}
	}
	x = x ^ n;
	int sum = 0;
	for (int i = 0; i < m; ++i)
		(sum += x.v[i][0]) %= mod;
	cout << sum << endl;
	return 0;
}

  

原文地址:https://www.cnblogs.com/akhpl/p/7116136.html