[HNOI2008]GT考试

[HNOI2008]GT考试

以前太菜, 一看到考试两字就劝退...

题意: 求有多少字符集为数字, 长度为n的字符串, 要求字符串中不能出现特定字串

不得不说这是一道字符串好题, 计数想\(dp\), \(f_{i,j}\)表示长度为\(i\), 匹配到\(j\)位方案数. 转移方程较为复杂, 考虑到\(f_{i,j}\)不止可以从\(f_{i-1,j-1}\)转移过来, 因为失配时可以像\(kmp\)那样找到最长匹配前缀, 预处理出数组\(g_{i,j}\)表示是否可以添加一个字符从匹配长度\(i\)到匹配长度\(j\). 这个\(kmp\)即可, 转移方程: \(f_{i,j} = \sum_{k=0}^{m-1}f_{i-1,k}*g_{k,j}\) 像不像矩阵乘法, 没错它就是. 矩阵快速幂一发救星了

\(warning\): 以下部分为本人\(yy\)

突然想起了在图论中也有矩阵乘法维护走k步的方案数, 现在想想, 图论和动态规划好像有着某些联系, 我们可以把图论的边想象成动态规划的转移, 点化为状态, 这可能也是\(floyd\)可以解决最短路问题的本质吧

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;

template <typename T>
void read(T &x) {
    x = 0; bool f = 0;
    char c = getchar();
    for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    for (;isdigit(c);c=getchar()) x=x*10+(c^48);
    if (f) x=-x;
}

template <typename T>
void write(T x) {
    if (x < 0) putchar('-'), x = -x;
    if (x >= 10) write(x / 10);
    putchar('0' + x % 10);
}

int n, m, P;

const int N = 23;
struct Matrix {
	int f[N][N];
	Matrix () {
		memset(f, 0, sizeof(f));
	}
	Matrix operator * (Matrix y) {
		Matrix tmp;
		for (int i = 0;i < m; i++) 
			for (int j = 0;j < m; j++) 
				for (int k = 0;k < m; k++) 
					tmp.f[i][j] = (tmp.f[i][j] + f[i][k] * y.f[k][j]) % P;
		return tmp;
	}
}I, M;

char s[N];

int nxt[N];
void prework() {
	nxt[1] = 0; int j = 0;
	for (int i = 2; i <= m; i++) {
		while (j && s[j+1] != s[i]) j = nxt[j];
		if (s[j+1] == s[i]) j++;
		nxt[i] = j;
	}
	for (int i = 0;i < m; i++) {
		for (int j = '0';j <= '9'; j++) {
			int k = i;
			while (k && s[k+1] != j) k = nxt[k];
			if (s[k+1] == j) k++;
			++M.f[i][k];
		}
	}
}

Matrix fpw(Matrix x, ll mi) {
	Matrix res = I;
	while (mi) {
		if (mi & 1) res = res * x;
		x = x * x;
		mi >>= 1;
	}
	return res;
}

int main() {
	read(n), read(m), read(P);
	scanf ("%s", s + 1); prework();
	for (int i = 0;i < m; i++) I.f[i][i] = 1;
	Matrix ans = fpw(M, n);
	ll res = 0;
	for (int i = 0;i < m; i++) res += ans.f[0][i];
	cout << res % P << endl;
	return 0;
}
posted @ 2020-01-28 20:06  Hs-black  阅读(118)  评论(0编辑  收藏  举报