[HDU6314] Matrix

前言

卡常去*吧

题目

HDU

题目大意:

有一个\(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,'\n');
	}
	return 0;
}
posted @ 2020-09-07 11:59  皮皮刘  阅读(140)  评论(0编辑  收藏  举报