[HDU-6314]Matrix题解

19 篇文章 0 订阅

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值