agc040_c Neither AB nor BA

题目叙述

agc037_c

求有多少个长为 (N)(N) 是偶数) 的字符串满足下列条件:

  • 只有A,B,C三种字符
  • 不断删掉除 AB 和 BA 以外长度为 2 的字符串可以删成空串

题解

进行巧妙转化。可以将字符串黑白染色(就是传统的相邻不同色)。可以发现,对于一个操作去掉相邻两位必然去掉一黑一白。那么将所有白色的 A 变成 B 白色的 B 变成 A,一次在原串消去 AB 相当于在新串消去两个相同的 A 或者相同的 B 。

下面考虑如何判断一个字符串是否可以删没。对于一个字符串,他转化后的字符串只要字符 A 、B的数量均不超过 (frac{n}{2}) 就可以。具体每回选出目前剩下数量最多的字符,配上另外一种字符删掉即可。

所以容斥计数就好了。

代码

#include <cstdio>
using namespace std;
typedef long long ll;
const int NC = 1e7 + 5, Mod = 998244353;
int Ml(int x, int y) { return (ll)x * y % Mod; }
int Ad(int x, int y) { return ((x + y) > Mod) ? (x + y - Mod) : (x + y); }
int Dc(int x, int y) { return ((x - y) < 0) ? (x - y + Mod) : (x - y); }
int ksm(int x, int y) {
	int ret = 1;
	for (; y; y >>= 1, x = Ml(x, x))
		if (y & 1) ret = Ml(ret, x);
	return ret;
}
int N, half, fac[NC], ifac[NC];
void Init() {
	fac[0] = 1;
	for (int i = 1; i <= N; ++i)
		fac[i] = Ml(fac[i-1], i);
	ifac[N] = ksm(fac[N], Mod - 2);
	for (int i = N-1; i >= 0; --i)
		ifac[i] = Ml(ifac[i+1], i+1);
}
int binom(int x, int y) {
	if (x < 0 || y < 0 || x < y)
		return 0;
	else return Ml(fac[x], Ml(ifac[y], ifac[x-y]));
}
int main() {
	scanf("%d", &N);
	half = N / 2 + 1;
	int ans = 0;
	Init();
	for (int i = half; i <= N; ++i) {
		ans = Ad(ans, Ml(binom(N, i), ksm(2, N-i)));
	}
	ans = Dc(ksm(3, N), Ml(ans, 2));
	printf("%d
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/YouthRhythms/p/13541225.html