版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/84291551
洛谷传送门
BZOJ传送门
题目描述
阿申准备报名参加 GT 考试,准考证号为 位数 ,他不希望准考证号上出现不吉利的数字。 他的不吉利数字 有 位,不出现是指 中没有恰好一段等于 , 和 可以为
输入输出格式
输入格式:
第一行输入 .接下来一行输入 位的数。
输出格式:
阿申想知道不出现不吉利数字的号码有多少种,输出模 取余的结果。
输入输出样例
输入样例#1:
4 3 100
111
输出样例#1:
81
说明
解题分析
看到 , 大概就能猜出这玩意是个矩阵了。
所以用 或 自动机搞出转移边, 表示在若干次操作后停留在 号节点的方案数, 跑一边矩阵快速幂即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define ll long long
int MOD, root, cnt, n, m;
int fail[25], son[25][10];
char buf[25];
bool tag[25];
std::queue <int> q;
struct Matrix {ll mat[21][21];} base, unit, start;
IN Matrix operator * (const Matrix &x, const Matrix &y)
{
Matrix ret;
R int i, j, k;
for (i = 0; i < 21; ++i)
for (j = 0; j < 21; ++j)
{
ret.mat[i][j] = 0;
for (k = 0; k < 21; ++k)
ret.mat[i][j] += x.mat[i][k] * y.mat[k][j];
ret.mat[i][j] %= MOD;
}
return ret;
}
Matrix fpow()
{
Matrix ret = unit;
W (n)
{
if (n & 1) ret = ret * base;
base = base * base, n >>= 1;
}
return ret;
}
void insert()
{
R int len = std::strlen(buf), now = root, id;
for (R int i = 0; i < len; ++i)
{
id = buf[i] - '0';
if (!son[now][id]) son[now][id] = ++cnt;
now = son[now][id];
}
tag[now] = true;
}
void build()
{
R int now = root;
for (R int i = 0; i < 10; ++i) if (son[now][i]) q.push(son[now][i]);
W (!q.empty())
{
now = q.front(); q.pop();
for (R int i = 0; i < 10; ++i)
{
if (son[now][i])
{
q.push(son[now][i]);
fail[son[now][i]] = son[fail[now]][i];
tag[son[now][i]] |= tag[fail[son[now][i]]];
}
else son[now][i] = son[fail[now]][i];
}
}
for (R int i = 0; i <= cnt; ++i)
{
for (R int j = 0; j < 10; ++j)
if (!tag[son[i][j]]) base.mat[i][son[i][j]]++;
}
for (R int i = 0; i < 21; ++i) unit.mat[i][i] = 1;
start.mat[0][0] = 1;
}
int main(void)
{
scanf("%d%d%d", &n, &m, &MOD);
scanf("%s", buf); insert(); build();
int ans = 0;
Matrix res = start * fpow();
for (R int i = 0; i <= cnt; ++i) ans = (ans + res.mat[0][i]) % MOD;
printf("%d", ans);
}