「HDU 6314」Matrix「容斥」

版权声明:本文为hzy原创文章,未经博主允许不可随意转载。 https://blog.csdn.net/Binary_Heap/article/details/81839405

题目传送门

题意

对一个 n m 的二维方格涂上黑白两色,求至少 a 行全黑, b 列全黑的方案数.

题解

可以先考虑行,然后考虑二维就十分简单了.

我们用 g ( k ) 表示至少有 k 行全黑的方案数,容斥求一下:

g ( k ) = i = k n f ( i ) C n i 2 n i

因为是至少,所以需要容斥, C n i 表示 n 行选 i 行, 2 n i 表示其中剩下的行状态随意, f ( k ) 为容斥系数,我们需要递推出这个容斥系数.

每个行数为 j 的答案计算贡献只能算一次,所以: i = k j f ( i ) C j i = 1

i = k n f ( i ) C n i

= i = k n 1 f ( i ) C n i + f ( n )

= i = k n 1 f ( i ) ( C n 1 i 1 + C n 1 i ) + f ( n )

= i = k n 1 ( f ( i ) C n 1 i 1 + f ( i ) C n 1 i ) + f ( n )

= 1 + i = k n 1 f ( i ) C n 1 i + f ( n )

因为 i = k n f ( i ) C n i = 1 ,因此 f ( n ) = i = k n 1 f ( i ) C n 1 i 1

O ( n 2 ) O ( m 2 ) 的时间递推出行列的容斥系数 f a f b ,然后就可以得到答案的式子:

a n s = i = a n j = b m f a ( i ) C n i f b ( j ) C m j 2 ( n i ) ( m j )

#include <cstdio> 

const int MAXN = 3000;
const int MOD = 998244353;

int n, m, a, b;
int fa[MAXN + 10], fb[MAXN + 10];
int pow2[MAXN * MAXN + 10], c[MAXN + 10][MAXN + 10];

void init() {
    pow2[0] = 1;
    for(int i = 1; i <= MAXN * MAXN; i ++)
        pow2[i] = (pow2[i - 1] * 2LL) % MOD;
    for(int i = 0; i <= MAXN; i ++) {
        c[i][0] = c[i][i] = 1;
        for(int j = 1; j < i; j ++)
            c[i][j] = (1ll * c[i-1][j-1] + c[i-1][j]) % MOD;
    }
}

void calc_f() {
    fa[a] = 1;
    for(int i = a + 1; i <= n; i ++) {
        fa[i] = 0;
        for(int j = a; j < i; j ++)
            fa[i] = (fa[i] + 1ll * c[i-1][j-1] * fa[j] % MOD) % MOD;
        fa[i] = ((-fa[i]) % MOD + MOD) % MOD;
    }
    fb[b] = 1;
    for(int i = b + 1; i <= m; i ++) {
        fb[i] = 0;
        for(int j = b; j < i; j ++)
            fb[i] = (fb[i] + 1ll * c[i-1][j-1] * fb[j] % MOD) % MOD;
        fb[i] = ((-fb[i]) % MOD + MOD) % MOD;
    }
}

int main() {
    init();
    while(~ scanf("%d%d%d%d", &n, &m, &a, &b)) {
        calc_f();
        int ans = 0;
        for(int i = a; i <= n; i ++)
            for(int j = b; j <= m; j ++)
                ans = (ans + 1ll * fa[i] * c[n][i] % MOD * fb[j] % MOD * c[m][j] % MOD * pow2[(n - i) * (m - j)] % MOD) % MOD; 
        printf("%d\n", (ans % MOD + MOD) % MOD);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Binary_Heap/article/details/81839405