2018 Multi-University Training Contest 2 06

题意

给定 \(w\times h\) 的矩形,每个格子黑白染色。
问有多少种染色方案使得至少 \(A\) 行,至少 \(B\) 列是黑的。

\(1\ \leq\ w,\ h,\ A,\ B\ \leq\ 3000\)

做法1

考虑容斥,容斥系数 \(coef(X,\ Y)\ =\ 1\ -\ \sum_{A\ \leq\ i\ \leq\ X}\ \sum_{B\ \leq\ j\ \leq\ Y}\ [i\ \neq\ X\ or\ j\ \neq\ Y]\ coef(i,\ j)\ \binom{X}{i}\ \binom{Y}{j}\)
可以证(da)明(biao)得 \(coef(X,\ Y)\ =\ coef(A,\ Y)\ coef(X,\ B),\ \forall\ X\ >\ A,\ Y\ >\ B\),因为行列是独立的。

代码

#include <bits/stdc++.h>

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#ifdef __WIN32
#define LLFORMAT "I64"
#else
#define LLFORMAT "ll"
#endif

using namespace std;

const int maxn = 3010, mod = 998244353;

int c[maxn][maxn], gA[maxn], gB[maxn], R, C, A, B, pw2[maxn * maxn];

void solve() {
	gA[B] = gB[A] = 1;
	if(A > R || B > C) { puts("0"); return; }
	for (int Y = B + 1; Y <= C; ++Y) {
		gA[Y] = 1;
		for (register int j = B, *foo = c[Y] + j; j < Y; ++j, ++foo) gA[Y] = ((long long) gA[Y] - (long long) gA[j] * *foo) % mod;
	}
	for (int X = A + 1; X <= R; ++X) {
		gB[X] = 1;
		for (register int i = A, *foo = c[X] + i; i < X; ++i, ++foo) gB[X] = ((long long) gB[X] - (long long) gB[i] * *foo) % mod;
	}
	for (int i = A, *foo = c[R] + i; i <= R; ++i, ++foo) gB[i] = (long long) gB[i] * *foo % mod;
	for (int j = B, *foo = c[C] + j; j <= C; ++j, ++foo) gA[j] = (long long) gA[j] * *foo % mod;
	int ans = 0;
	for (register int i = A, *foo = gB + i, a = R - i; i <= R; ++i, ++foo, --a) for (register int j = B, *bar = gA + j, b = C - j; j <= C; ++j, ++bar, --b) {
		ans = ((long long) *foo * *bar % mod * pw2[a * b] + ans) % mod;
	}
	printf("%d\n", (ans + mod) % mod);
	return;
}

int main() {
	pw2[0] = 1; for (int i = 1; i <= 9000000; ++i) pw2[i] = (pw2[i - 1] << 1) % mod;
	for (int i = 0; i < maxn; ++i) for (int j = c[i][0] = 1; j <= i; ++j) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
	while(scanf("%d%d%d%d", &R, &C, &A, &B) == 4) solve();
	return 0;
}
posted @ 2018-09-09 21:40  King_George  阅读(98)  评论(0编辑  收藏  举报