loading...

[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;
}
posted @ 2025-05-17 18:39  goldspade  阅读(31)  评论(0)    收藏  举报