前言
卡常去*吧
题目
题目大意:
有一个(n*m)的矩阵,对其进行黑白染色,问至少有(A)行(B)列为黑色的方案数
答案对(998244353)取模
讲解
首先不难想到容斥,这道题的难点在于如何求出容斥系数
令(a_i(A<=i))表示(i)行颜色为黑的容斥系数
易得边界(a_A=1),普遍的(a_i=1-sum_{j=A}^{i-1}a_j*C_{i}^{j})(本身有1种,减去其它的(a_j)算上的它)
同理,(b_i=1-sum_{j=B}^{i-1}b_j*C_{i}^{j})
所以最终答案为(sum_{i=A}^{n}sum_{j=B}^{m}a_i*b_j*C_n^i*C_m^j*2^{(n-i)(m-j)})
最后乘上的(2^{(n-i)(m-j)})为剩余格子随便选的方案数
注意:
如果用阶乘逆元的方法求组合数会(TLE)(或者是我常数太大qwq,要用杨辉三角递推
代码
int mi[MAXN * MAXN],c[MAXN][MAXN];
void pre(int x)
{
mi[0] = 1;
c[0][0] = 1;
for(int i = 1;i <= x;++ i)
{
c[i][0] = 1;
for(int j = 1;j <= i;++ j)
c[i][j] = (c[i-1][j-1] + c[i-1][j]) % MOD;
}
for(int i = 1;i <= x*x;++ i)
mi[i] = (mi[i-1] << 1) % MOD;
}
int C(int x,int y)
{
if(x < y) return 0;
return c[x][y];
}
int a[MAXN],b[MAXN];//容斥系数
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
pre(3000);
while(~scanf("%d %d",&n,&m))
{
A = Read(); B = Read();
for(int i = A;i <= n;++ i)
{
a[i] = 1;
for(int j = A;j < i;++ j)
a[i] = (a[i] - 1ll * a[j] * C(i,j) % MOD + MOD) % MOD;
}
for(int i = B;i <= m;++ i)
{
b[i] = 1;
for(int j = B;j < i;++ j)
b[i] = (b[i] - 1ll * b[j] * C(i,j) % MOD + MOD) % MOD;
}
int ans = 0;
for(int i = A;i <= n;++ i)
for(int j = B;j <= m;++ j)
ans = (ans + 1ll * a[i] * b[j] % MOD * C(n,i) % MOD * C(m,j) % MOD * mi[(n-i) * (m-j)]) % MOD;
Put(ans,'
');
}
return 0;
}