hdu6314 容斥+数学

题意 : n*m的矩阵 可以涂黑白两色 问至少A行B列为黑色的涂色方案种类数,答案对998244353取模,1<=n,m,A,B<=3000

题解:  ans=sum{A,..n}sum(B,...m}*f[n-i][m-j] (i,j分别为前两个∑的迭代变量),f[a][b]表示a行b列中没有一行或者一列全部涂黑

             由容斥定理 f[i][j]=sum{0,..i}sum{0,.j}*(-1)(a+b)*2(i-a)*(j-b)   (a,b分别为前两个∑的迭代变量)。

            代入得ans=sum{A,...n}sum{B,...m}sum{0,....n-i}sum{0,...m-j} n!m!(-1)a+b2(n-i-a)(m-j-b) /((n-i-a)!(m-j-b)!i!j!a!b!)        (i,j,a,b)分别∑为的迭代变量

         

 

#include<cstdio>
using namespace std;
const int P=998244353;
const int N=3e3+7;
int e[N*N],fac[N],facn[N*N],pre[N][N],g[N][N];
inline int ksm(int x,int k){
    int ans=1;
    for(;k;k>>=1,x=1LL*x*x%P) if(k&1) ans=1LL*ans*x%P;
    return ans;
}
void init(){
    int i,val;
    for(e[0]=i=1;i<=9000000;++i) e[i]=2LL*e[i-1]%P;
    for(fac[0]=facn[0]=i=1;i<=3000;++i) fac[i]=1LL*i*fac[i-1]%P,facn[i]=ksm(fac[i],P-2);
    for(int i=0;i<=3000;++i) for(int j=i;j>=0;--j) {
        val=1LL*facn[j]*facn[i-j]%P;
        if((i-j)&1) val=P-val;
        pre[i][j]=(val+pre[i][j+1])%P;
    }
    for(int i=0;i<=3000;++i) for(int j=0;j<=3000;++j)
    g[i][j]=1LL*e[i*j]*facn[i]%P*facn[j]%P;
}
int main(){
    init();
    int n,m,A,B;
    while(~scanf("%d%d%d%d",&n,&m,&A,&B)){
        int ans=0;
        for(int i=0;i<=n-A;++i) for(int j=0;j<=m-B;++j) 
        ans=(ans+1LL*pre[n-i][A]*pre[m-j][B]%P*g[i][j]%P)%P;
        printf("%d\n",1LL*ans*fac[n]%P*fac[m]%P);
    }
}

 

posted @ 2018-07-27 15:03 Billyshuai 阅读(...) 评论(...) 编辑 收藏