GT 考试

// GT 考试.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

/*
* http://ybt.ssoier.cn:8088/problem_show.php?pid=1646
阿申准备报名参加 GT 考试,准考证号为 n 位数 X1X2⋯Xn(0≤Xi≤9),他不希望准考证号上出现不吉利的数字。
他的不吉利数字 A1A2⋯Am(0≤Ai≤9) 有 m 位,不出现是指 X1X2⋯Xn 中没有恰好一段等于 A1A2⋯Am ,A1和 X1 可以为 0。

【输入】
第一行输入 n,m,K,接下来一行输入 m 位的数。

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

【输入样例】
4 3 100
111
【输出样例】
81
【提示】
数据范围与提示:

对于全部数据,1≤n≤109,1≤m≤20,2≤K≤1000。
*/

#include <iostream>
#include <cstring>

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])  // c = a * b
{
	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;
}

posted on 2025-03-31 17:41  itdef  阅读(10)  评论(0)    收藏  举报

导航