[hdu6314]Matrix
Description
求 \(n \times m\) 的网格黑白染色方案数,满足有至少 \(A\) 行全部为黑色,至少 \(B\) 列全部为黑色。
Solution
考虑容斥。
假设性质 \(R_i\) 表示至少 \(i\) 行被染成黑色,\(C_i\) 表示至少 \(i\) 列被染成白色。
令 \(s(P)\) 表示具有性质 \(P\) 的染色方案数。
答案求的 \(s(R_A\land C_B)\) 真是相当的求不了。
很快能想到一个式子:令 \(t(a,b)=\dbinom{n}{a}\dbinom{m}{b}2^{(n-a)(m-b)}\)。这个东西有很多重复计数,考虑怎么去除。令 \(s(R_A\land C_B)=\displaystyle\sum_{i=A}^n\sum_{j=B}^m a_ib_jt(i,j)\)。(\(a,b\) 独立可拆分)
先考虑 \(a\),显然,我们假设去了重之后希望在每一次都只加上恰为 \(i\) 行染黑的方案数,\(a_A=1\),\(\forall i >A:a_i=1-\displaystyle\sum _{j=A}^{i-1}\dbinom{i}{j}a_i\)。
\(b\) 是同样的递推方法。
综上可以直接算答案了。
快点这里看代码
#include <bits/stdc++.h>
using namespace std;
#define _f(i, l, r) for (int i = l; i <= r; ++i)
#define _r(i, r, l) for (int i = r; i >= l; --i)
#define FASTIO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define LL long long
#define int long long
#define PII pair<int,int>
#define MOD(p) ((p)>=mod?(p)-mod:(p))
#define pb push_back
#define eb emplace_back
const int N = 3005, mod = 998244353;
template<typename Tp>
inline void tomax(Tp& x, Tp y) { x<y?(x=y):(x);}
template<typename Tp>
inline void tomin(Tp& x, Tp y) { x>y?(x=y):(x); }
inline void cadd(int& x, int y) { x = (x+y)%mod;}
int n, m, A, B;
int C[N][N], po[N*N];
inline void prework(int n) {
_f(i, 0, n) {
C[i][0] = 1;
_f(j, 1, i)
C[i][j] = MOD(C[i-1][j-1]+C[i-1][j]);
}
po[0] = 1;
_f(i, 1, n*n)
po[i] = MOD(po[i-1]<<1);
}
int a[N], b[N];
inline void solve() {
_f(i, A, n) {
a[i] = 1;
_f(j, A, i-1)
cadd(a[i], (mod-C[i][j])*a[j]);
}
_f(i, B, m) {
b[i] = 1;
_f(j, B, i-1)
cadd(b[i], (mod-C[i][j])*b[j]);
}
int ans = 0;
_f(i, A, n)
_f(j, B, m)
cadd(ans, a[i]*b[j]%mod*C[n][i]%mod*C[m][j]%mod*po[(n-i)*(m-j)]);
cout << ans << '\n';
}
signed main() {
FASTIO;
int _ = 0;
prework(3000);
while (cin >> n >> m >> A >> B) solve();
return 0;
}

浙公网安备 33010602011771号