abc273G题解

我们用 \(dp_{i,j}\) 表示考虑到前 \(i\) 行,有 \(j\)\(2\) 的方案数。

设有 \(k\)\(1\)(因为我们对于每一行都有固定的和,所以 \(k\) 计算可得)。

  • \(a_{i+1} = 0\)

    • \(dp_{i,j} \to dp_{i+1,j}\)
  • \(a_{i+1}=1\)

    • \(dp_{i,j}\times(n-j-k) \to dp_{i+1,j}\)

    • \(dp_{i,j}\times k \to dp_{i+1,j+1}\)

  • \(a_{i+1}=2\)

    • \(dp_{i,j}\times \tbinom{n-j-k}{2} \to dp_{i+1,j}\)

    • \(dp_{i,j} \times (n - j - k) \times k \to dp_{i+1,j+1}\)

    • \(dp_{i,j} \times \tbinom{k}{2} \to dp_{i+1,j+2}\)

    • \(dp_{i,j} \times \tbinom{n-j-k}{1} \to dp_{i,j+1}\)

组合数公式:
\(\tbinom{n}{m} = \frac{n!}{(n-m)!m!}\)

AcCode:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int N = 1e4 + 10, inf = INT_MAX, P = 998244353;
int n;
int a[N], b[N], sum[N];
ll dp[N], tmp[N], f[N], inv[N];

ll rp(ll a, int b) {
	ll res = 1;
	for (; b; (a *= a) %= P, b /= 2)
		if (b & 1)
			(res *= a) %= P;
	return res;
}

void init() {
	f[0] = 1;
	for (int i = 0; i <= n; i++) {
		if (i) f[i] = f[i - 1] * i % P;
		inv[i] = rp(f[i], P - 2);
	}
}

ll C(int a, int b) {
	if (a < b) return 0;
	return f[a] * inv[a - b] % P * inv[b] % P;
}

int main() {
	scanf("%d", &n);
	init();
	int cnt = 0, t1 = 0, t2 = 0;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		sum[i] = sum[i - 1] + a[i];
		t1 += a[i];
	}
	for (int i = 1; i <= n; i++) {
		scanf("%d", &b[i]);
		cnt += (b[i] == 2);
		t2 += b[i];
	}
	if (t1 != t2) {
		puts("0");
		return 0;
	}
	tmp[0] = 1;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= n; j++) {
			int k = sum[i] - j * 2;// k个1
			if (!tmp[j] || k < 0 || n - j - k < 0) continue;
			if (a[i + 1] == 0)
				(dp[j] += tmp[j]) %= P;
			else if (a[i + 1] == 1) {
				(dp[j] += tmp[j] * (n - j - k) % P) %= P;
				(dp[j + 1] += tmp[j] * k % P) %= P;
			} else {
				(dp[j] += tmp[j] * C(n - j - k, 2) % P) %= P;
				(dp[j + 1] += tmp[j] * (n - j - k) % P * k % P) %= P;
				(dp[j + 1] += tmp[j] * C(n - j - k, 1) % P) %= P;
				(dp[j + 2] += tmp[j] * C(k, 2) % P) %= P;
			}
		}
		for (int j = 0; j <= n; j++) {
			tmp[j] = dp[j];
			dp[j] = 0;
		}
	}
	int tot = sum[n] - cnt * 2;
	ll ans = tmp[cnt];
	ans = ans * rp(C(n, cnt), P - 2) % P;
	ans = ans * rp(C(n - cnt, tot), P - 2) % P;
	printf("%lld\n", ans);
	return 0;
}
posted @ 2023-01-19 14:40  weirdoX  阅读(49)  评论(0)    收藏  举报