1. 程式人生 > 實用技巧 >CF1237F Balanced Domino Placements

CF1237F Balanced Domino Placements

CF1237F Balanced Domino Placements
題讀錯了。。。
對於一個骨牌的每個格子,不能有其他骨牌的格子和它在同一列同一行。
那麼行列分開單獨考慮。

  • \(f_{i,j}\) 為前 \(i\) 行放了幾個佔了兩個格子的。
  • \(g_{i,j}\) 為前 \(i\) 列放了幾個佔了兩個格子的。

\(\begin{cases} f_{i,j} = f_{i-1,j} + f_{i-2,j-1} \cdot [2 \le i \&j \&!row_i\&!row_{i-1}] \\ g_{i,j} = g_{i-1,j} + g_{i-2, j-1} \cdot [2 \le i \&j\& !col_i \ \ \&!col_{i-1} \ \ ]\end{cases}\)

最後答案就是 \(f_{N,i} \cdot g_{M,j} \cdot C_{sumx - 2 \cdot i}^{j} \cdot C_{sumy - 2 \cdot j}^i \cdot i! \cdot j!\)

/*
	Name: 1237F
	Author: Gensokyo_Alice
	Date: 2020/11/16
	Description:
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
const ll MAXN = 4e3+10, MOD = 998244353;

ll N, M, K, col[MAXN], row[MAXN], sumx, sumy, fac[MAXN], inv[MAXN], ans, f[MAXN][MAXN], g[MAXN][MAXN];

ll P(ll, ll);

int main() {
	scanf("%lld%lld%lld", &N, &M, &K);
	for (ll x, y, xx, yy, i = 1; i <= K; i++) {
		scanf("%lld%lld%lld%lld", &x, &y, &xx, &yy);
		col[y] = col[yy] = row[x] = row[xx] = 1;
	}
	inv[0] = inv[1] = fac[0] = fac[1] = 1;
	for (ll i = 2, k = MAXN - 10; i <= k; i++) inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD, fac[i] = fac[i-1] * i % MOD;
	for (ll i = 1, k = MAXN - 10; i <= k; i++) (inv[i] *= inv[i-1]) %= MOD; 
	for (ll i = 1; i <= N; i++) sumx += !row[i];
	for (ll i = 1; i <= M; i++) sumy += !col[i];
	f[0][0] = g[0][0] = 1;
	for (ll i = 1; i <= N; i++)
		for (ll j = 0; 2 * j <= sumx; j++)
			f[i][j] = (f[i-1][j] + ((j && i >= 2 && !row[i] && !row[i-1]) ? f[i-2][j-1] : 0)) % MOD;
	for (ll i = 1; i <= M; i++)
		for (ll j = 0; 2 * j <= sumy; j++)
			g[i][j] = (g[i-1][j] + ((j && i >= 2 && !col[i] && !col[i-1]) ? g[i-2][j-1] : 0)) % MOD; 
	for (ll i = 0; i * 2 <= sumx; i++)
		for (ll j = 0; j * 2 <= sumy; j++)
			(ans += f[N][i] * g[M][j] % MOD * P(j, sumx - 2 * i) % MOD * P(i, sumy - 2 * j) % MOD) %= MOD;
    printf("%lld", ans);
	return 0;
}

ll P(ll m, ll n) {
	if (m > n) return 0;
	return fac[n] * inv[n-m] % MOD;
}