CF506E题解

看到这题还没有吊打标程的BM题解,神larryzhong(即hellomath)连连怒斥。

larryzhong说这是BM板子,没什么讲的意义,不会的自行百度。

下面贴上larryzhong吊打标程的代码:

#include 
using namespace std;

const int P = 10007;
int n, m, tot, f[2][210][210];
char s[210];
struct mat { unsigned long long a[300][300]; } A, B;

mat operator * (const mat &A, const mat &B) {
	static mat C; memset(C.a, 0, sizeof(C.a));
	for (int i = 1; i <= tot; i++) {
		for (int j = 1; j <= tot; j++) if (A.a[i][j]) {
			for (int k = 1; k <= tot; k++) {
				C.a[i][k] += A.a[i][j] * B.a[j][k];
			}
		}
	}
	for (int i = 1; i <= tot; i++) {
		for (int j = 1; j <= tot; j++) {
			C.a[i][j] %= P;
		}
	}
	return C;
}

int qp(int x, int y) {
	int z = 1;
	for (; y; y >>= 1, x = 1LL * x * x % P) {
		if (y & 1) z = 1LL * z * x % P;
	}
	return z;
}

int main() {
	scanf("%s %d", s + 1, &n); m = strlen(s); n += m;
	vector<int> V;
	int cur = 1, nxt = 0;
	f[1][1][m] = 1;
	for (int i = 1, ans = 0; i <= 1000; i++, swap(cur, nxt)) {
		memset(f[nxt], 0, sizeof(f[nxt]));
		ans = ans * 26 % P;
		for (int j = 1; j <= m + 1; j++) {
			for (int k = 0; k < j; k++) {
				(ans += f[cur][j][k]) %= P;
			}
		}
		if (!(n & 1)) V.push_back(ans);
		int ans2 = ans * 26 % P;
		for (int j = 1; j <= m; j++) {
			(ans2 += f[cur][j][j]) %= P;
		}
		if (n & 1) V.push_back(ans2);
		for (int j = 1; j <= m; j++) {
			for (int k = j; k <= m; k++) if (f[cur][j][k]) {
				if (s[j] == s[k]) {
					(f[nxt][j][k] += 25 * f[cur][j][k]) %= P;
					(f[nxt][j + 1][k - 1] += f[cur][j][k]) %= P;
				} else {
					(f[nxt][j][k] += 24 * f[cur][j][k]) %= P;
					(f[nxt][j][k - 1] += f[cur][j][k]) %= P;
					(f[nxt][j + 1][k] += f[cur][j][k]) %= P;
				}
			}
		}
	}
	n = n >> 1;
	if (n < V.size()) printf("%d\n", V[n]), exit(0);
	auto BM = [&](vector<int> a, int n) {
		vector<int> lst, ans;
		int w = 0, delta = 0;
		for (int i = 1; i <= n; i++) {
			int tmp = 0;
			for (int j = 0; j < ans.size(); j++) {
				tmp = (tmp + a[i - 1 - j] * ans[j]) % P;
			}
			if ((a[i] - tmp) % P == 0) continue;
			if (!w) {
				w = i, delta = a[i] - tmp;
				for (int j = i; j; j--) ans.push_back(0);
				continue;
			}
			vector<int> now = ans;
			int mul = (a[i] - tmp) * qp(delta, P - 2) % P;
			if (ans.size() < lst.size() + i - w) {
				ans.resize(lst.size() + i - w);
			}
			ans[i - w - 1] = (ans[i - w - 1] + mul) % P;
			for (int j = 0; j < lst.size(); j++) {
				ans[i - w + j] = (ans[i - w + j] - mul * lst[j]) % P;
			}
			if (now.size() - i < lst.size() - w) {
				lst = now, w = i, delta = a[i] - tmp;
			}
		}
		for (int& x : ans) x = (x + P) % P;
		return ans;
	};
	auto ans = BM(V, V.size() - 1);
	tot = ans.size();
	for (int i = 1; i <= tot; i++) {
		if (i > 1) A.a[i][i - 1] = 1;
		A.a[i][tot] = ans[tot - i], B.a[1][i] = V[V.size() - 1 - tot + i];
	}
	for (int t = n - V.size() + 1; t; t >>= 1, A = A * A) {
		if (t & 1) B = B * A;
	}
	printf("%llu\n", B.a[1][tot]);
	return 0;
}

你可能感兴趣的:(CF506E题解)