题目叙述
求有多少个长为 (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;
}