[HDU-6314]Matrix题解

f [ i ] [ j ] 表 示 恰 好 有 i 行 j 列 为 黑 色 g [ i ] [ j ] 表 示 一 个 i 行 j 列 的 矩 阵 染 色 满 足 每 一 行 每 一 列 至 少 有 一 个 白 色 格 子 的 方 案 数 f[i][j] 表示恰好有 i 行 j 列为黑色 \\ g[i][j] 表示一个 i 行 j 列的矩阵染色满足每一行每一列至少有一个白色格子的方案数 f[i][j]ijg[i][j]ij


转移:

f [ i ] [ j ] = ( n i ) ( m j ) × g [ n − i ] [ m − j ] f[i][j] = \binom{n}{i} \binom{m}{j} \times g[n - i][m - j] f[i][j]=(in)(jm)×g[ni][mj]

意义:在 n × m n \times m n×m 的矩阵中分别在 n n n 行中选 i i i 行和在 m m m 列中选 j j j 列全部染成黑色,然后剩余部分染色不能出现一行黑或一列黑,这时我们可以如下图所示,把选择的行列去掉再拼合起来,剩余部分染色不出现一行黑或一列黑的方案数即拼合后的矩阵不出现一行黑或一列黑。

在这里插入图片描述

g [ i ] [ j ] = ∑ x = 0 i ∑ y = 0 j ( − 1 ) x + y 2 ( i − x ) × ( j − y ) ( i x ) ( j y ) g[i][j] = \sum_{x = 0}^{i} \sum_{y = 0}^{j} (-1)^{x + y}2^{(i - x) \times (j - y)}\binom{i}{x} \binom{j}{y} g[i][j]=x=0iy=0j(1)x+y2(ix)×(jy)(xi)(yj)

意义:

考虑选择 r r r 行, c c c 列全为黑的这一类染色方案受到的贡献。

对于一种具体的方案,容斥中对它的贡献(系数)如下式。

[ r ≠ 0 ] o r [ c ≠ 0 ] [r \neq 0] or [c \neq 0] [r=0]or[c=0]

      ∑ p = 0 r ∑ q = 0 c ( − 1 ) p + q ( r p ) ( c q ) = ∑ p = 0 r ( r p ) ∑ q = 0 c ( − 1 ) p + q ( c q ) = ∑ p = 0 r ( r p ) × 0 = 0 \begin{aligned} & \ \ \ \ \ \sum_{p = 0}^{r}\sum_{q = 0}^{c}(-1)^{p + q}\binom{r}{p}\binom{c}{q} \\ &= \sum_{p = 0}^{r} \binom{r}{p} \sum_{q = 0}^{c} (-1)^{p + q} \binom{c}{q} \\ &= \sum_{p = 0}^{r}\binom{r}{p} \times 0 \\ &= 0 \end{aligned}      p=0rq=0c(1)p+q(pr)(qc)=p=0r(pr)q=0c(1)p+q(qc)=p=0r(pr)×0=0

式子的意义:

考虑这种具体方案会被算几次:即它不同的 / 指定某些行、列全为黑色 / 的方案数 * 容斥系数。

因为最后的模样相同,所以只有选择的行、列全为黑的方案不一样,才会被重复计算。

举个例子

在这里插入图片描述
这张图,它会被
x = 1 , y = 2 x = 1, y = 2 x=1,y=2 计算一次
x = 1 , y = 1 x = 1, y = 1 x=1,y=1 计算两次 (列全为黑有两种选法)
x = 1 , y = 0 x = 1, y = 0 x=1,y=0 计算一次
x = 0 , y = 1 x = 0, y = 1 x=0,y=1 计算一次
x = 0 , y = 0 x = 0, y = 0 x=0,y=0 计算一次
容斥下来,计算了零次

r = c = 0 r = c = 0 r=c=0

( − 1 ) 0 + 0 ( 0 0 ) ( 0 0 ) = 1 (-1)^{0 + 0} \binom{0}{0} \binom{0}{0} = 1 (1)0+0(00)(00)=1

所以它不会被算重,也不会被算漏。


优化:

a n s = ∑ i = a n ∑ j = b m ( n i ) ( m j ) ∑ x = 0 n − i ∑ y = 0 m − j ( − 1 ) x + y 2 ( n − i − x ) × ( m − j − y ) ( n − i x ) ( m − j y ) \begin{aligned} ans &= \sum_{i = a}^{n} \sum_{j = b}^{m} \binom{n}{i} \binom{m}{j} \sum_{x = 0}^{n - i} \sum_{y = 0}^{m - j} (-1)^{x + y}2^{(n - i - x) \times (m - j - y)}\binom{n - i}{x} \binom{m - j}{y} \end{aligned} ans=i=anj=bm(in)(jm)x=0niy=0mj(1)x+y2(nix)×(mjy)(xni)(ymj)

令 s = i + x , t = j + y 令 s = i + x, t = j + y s=i+x,t=j+y

i = s − x , j = t − y , a ≤ s ≤ n , b ≤ t ≤ m i = s - x, j = t - y, a \leq s \leq n, b \leq t \leq m i=sx,j=ty,asn,btm

{ x ≤ n − i y ≤ m − j a ≤ i ≤ n b ≤ j ≤ m ⇒ { s − n ≤ x ≤ s − a t − m ≤ y ≤ t − b ∴ { max ⁡ ( 0 , s − n ) ≤ x ≤ s − a max ⁡ ( 0 , t − m ) ≤ y ≤ t − b 又 ∵ { s ≤ n t ≤ m ∴ { s − n ≤ 0 t − m ≤ 0 ∴ { 0 ≤ x ≤ s − a 0 ≤ y ≤ t − b \begin{aligned} &\begin{cases} x \leq n - i \\ y \leq m - j \\ a \leq i \leq n \\ b \leq j \leq m \end{cases} \Rightarrow \begin{cases} s - n \leq x \leq s - a \\ t - m \leq y \leq t - b \end{cases} \\ \therefore &\begin{cases} \max (0, s - n) \leq x \leq s - a\\ \max (0, t - m) \leq y\leq t - b \end{cases} \\ 又 &\because \begin{cases} s \leq n \\ t \leq m \end{cases} \\ \therefore &\begin{cases} s - n \leq 0 \\ t - m \leq 0 \end{cases} \\ \therefore &\begin{cases} 0 \leq x \leq s - a \\ 0 \leq y \leq t - b \end{cases} \\ \end{aligned} xniymjainbjm{snxsatmytb{max(0,sn)xsamax(0,tm)ytb{sntm{sn0tm0{0xsa0ytb

a n s = ∑ s = a n ∑ t = b m ∑ x = 0 s − a ∑ y = 0 t − b ( − 1 ) x + y ( n s − x ) ( m t − y ) 2 ( n − s ) × ( m − t ) ( n − s + x x ) ( m − t + y y ) = ∑ s = a n ∑ t = b m 2 ( n − s ) × ( m − t ) ( ∑ x = 0 s − a ( − 1 ) x ( n s − x ) ( n − s + x x ) ) ( ∑ y = 0 t − b ( − 1 ) y ( m t − y ) ( m − t + y y ) ) \begin{aligned} ans &= \sum_{s = a}^{n}\sum_{t = b}^{m}\sum_{x = 0}^{s - a}\sum_{y = 0}^{t - b} (-1)^{x + y} \binom{n}{s - x} \binom{m}{t - y} 2^{(n - s) \times (m - t)} \binom{n - s + x}{x} \binom{m - t + y}{y} \\ &= \sum_{s = a}^{n}\sum_{t = b}^{m} 2^{(n - s) \times (m - t)} \Bigg( \sum_{x = 0}^{s - a} (-1)^x \binom{n}{s - x} \binom{n - s + x}{x} \Bigg) \Bigg( \sum_{y = 0}^{t - b} (-1)^y \binom{m}{t - y} \binom{m - t + y}{y} \Bigg) \end{aligned} ans=s=ant=bmx=0say=0tb(1)x+y(sxn)(tym)2(ns)×(mt)(xns+x)(ymt+y)=s=ant=bm2(ns)×(mt)(x=0sa(1)x(sxn)(xns+x))(y=0tb(1)y(tym)(ymt+y))

然后我们愉快的
发现,左边部分 ∑ x = 0 s − a ( − 1 ) x ( n s − x ) ( n − s + x x ) \sum_{x = 0}^{s - a} (-1)^x \binom{n}{s - x} \binom{n - s + x}{x} x=0sa(1)x(sxn)(xns+x) 只与 s s s 有关,所以可以 ↗预↘处↗理↘。

同样的,右边部分 ∑ y = 0 t − b ( − 1 ) y ( m t − y ) ( m − t + y y ) \sum_{y = 0}^{t - b} (-1)^y \binom{m}{t - y} \binom{m - t + y}{y} y=0tb(1)y(tym)(ymt+y) 只与 t t t 有关,也可以 ↗预↘处↗理↘。

β ( s ) = ∑ x = 0 s − a ( − 1 ) x ( n s − x ) ( n − s + x x ) γ ( t ) = ∑ y = 0 t − b ( − 1 ) y ( m t − y ) ( m − t + y y ) \beta(s) = \sum_{x = 0}^{s - a} (-1)^x \binom{n}{s - x} \binom{n - s + x}{x} \\ \gamma(t) = \sum_{y = 0}^{t - b} (-1)^y \binom{m}{t - y} \binom{m - t + y}{y} β(s)=x=0sa(1)x(sxn)(xns+x)γ(t)=y=0tb(1)y(tym)(ymt+y)

预处理出 β , γ \beta,\gamma βγ 后化简式子。

a n s = ∑ s = 0 n ∑ t = 0 m 2 ( n − s ) × ( m − t ) β ( s ) γ ( t ) \begin{aligned} ans &= \sum_{s = 0}^{n} \sum_{t = 0}^{m} 2^{(n - s) \times (m - t)} \beta(s) \gamma (t) \end{aligned} ans=s=0nt=0m2(ns)×(mt)β(s)γ(t)


参考代码

#include <cmath>
#include <vector>
#include <cstdio>
#include <cstdlib> 
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
#define ULL unsigned long long
#define PII pair <int, int>
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); i++)
#define per(i,j,k) for (int i = (j); i >= (k); i--)

template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
template <typename T>
void read (T &x) {
    x = 0; T f = 1;
    char ch = getchar ();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar ();
    }
    x *= f;
}
char For_Print[25];
template <typename T>
void write (T x) {
    if (x == 0) { putchar ('0'); return; }
    if (x < 0) { putchar ('-'); x = -x; }
    int poi = 0;
    while (x) {
        For_Print[++poi] = x % 10 + '0';
        x /= 10;
    }
    while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
    write (x); putchar (ch);
}

const LL Maxn = 3000;
const LL Mod = 998244353;

LL n, m, a, b;
LL c[Maxn + 5][Maxn + 5];
LL beta[Maxn + 5], gamma[Maxn + 5];

void add (LL &x, LL y) { (x += y) >= Mod && (x -= Mod); }
void del (LL &x, LL y) { (x -= y) < 0 && (x += Mod); }
LL md (LL x) { return x - x / Mod * Mod; }
LL quick_pow (LL x, LL y) {
    LL res = 1;
    while (y) {
        if (y & 1) res = (res * x) % Mod;
        x = (x * x) % Mod; y >>= 1;
    }
    return res;
}
LL inv (LL x) {
    return quick_pow (x, Mod - 2);
}
LL C (LL x, LL y) {
    return c[x][y];
}

int main () {
    
    c[0][0] = 1;
    rep (i, 1, Maxn)
        rep (j, 0, i) {
            add (c[i][j], c[i - 1][j]);
            add (c[i][j], (j - 1 >= 0 ? c[i - 1][j - 1] : 0));
        }

    while (~scanf ("%lld %lld %lld %lld", &n, &m, &a, &b)) {
        memset (beta, 0, sizeof beta);
        memset (gamma, 0, sizeof gamma);
        rep (s, 0, n)
            rep (x, 0, s - a)
                if (x & 1) del (beta[s], c[n][s - x] * c[n - s + x][x] % Mod);
                else add (beta[s], c[n][s - x] * c[n - s + x][x] % Mod);
        rep (t, 0, m)
            rep (y, 0, t - b)
                if (y & 1) del (gamma[t], c[m][t - y] * c[m - t + y][y] % Mod);
                else add (gamma[t], c[m][t - y] * c[m - t + y][y] % Mod);

        // /*
        LL res = 0;
        per (s, n, 0) {
            LL tmp = quick_pow (2, n - s), Now = 1;
            per (t, m, 0) {
                add (res, Now * beta[s] % Mod * gamma[t] % Mod);
                Now = (Now * tmp) % Mod;
            }
        }
        // */

        /*
        LL res = 0;
        rep (i, a, n)
            rep (j, b, m)
                rep (x, 0, n - i)
                    rep (y, 0, m - j)
                        if (x + y & 1) del (res, C (n, i) * C (m, j) % Mod * quick_pow (2, ((n - i) - x) * ((m - j) - y)) % Mod * C (n - i, x) % Mod * C (m - j, y) % Mod);
                        else add (res, C (n, i) * C (m, j) % Mod * quick_pow (2, ((n - i) - x) * ((m - j) - y)) % Mod * C (n - i, x) % Mod * C (m - j, y) % Mod);
        */
        /*
        LL res = 0;
        rep (s, a, n)
            rep (t, b, m)
                rep (x, 0, s - a)
                    rep (y, 0, t - b)
                        if (x + y & 1) del (res, C (n, s - x) * C (m, t - y) % Mod * quick_pow (2, (n - s) * (m - t)) % Mod * C (n - s + x, x) % Mod * C (m - t + y, y) % Mod);
                        else add (res, C (n, s - x) * C (m, t - y) % Mod * quick_pow (2, (n - s) * (m - t)) % Mod * C (n - s + x, x) % Mod * C (m - t + y, y) % Mod);
        */
        print (res, '\n');
    }
    return 0;
}
posted @ 2021-11-17 16:58  C2022lihan  阅读(26)  评论(0编辑  收藏  举报