Description
有一个N*M的棋盘,初始每个格子都是白色的。
行操作是指选定某一行,将这行所有格子的颜色取反(黑白互换)。
列操作是指选定某一列,将这列所有格子的颜色取反。
XX进行了R次行操作C次列操作(可能对某行或者某列操作了多次),最后棋盘上有S个黑色格子。
问有多少种不同的操作方案。两种操作方案不同,当且仅当对某行或者某列操作次数不同(也就是说与操作的顺序无关)。
方案数可能很大,输出它对10^9+7取模的结果。
Input
输入只有5个整数N,M,R,C,S。
N,M,R,C≤100000,0≤S≤N*M。
Output
输出有且仅有一个整数,表示答案对10^9+7取模的结果。
对行和列分别考虑,若有a行操作奇数次,b列操作奇数次,则有am+bn-ab个格子为黑色,可以枚举a求出对应的b,这时问题转化为n个物品分成k段,有x段含奇数个物品的方案数,打表可知当n-x为奇数时方案数为0,否则方案数为C(k-1+(n-x)/2,k-1)*C(k,x)
#include<cstdio> typedef long long i64; const int P=1000000007; int n,m,a,b; i64 s,ans=0; int iv[210007],fiv[210007],fac[210007]; i64 C(int n,int m){ if(n<m)return 0; return i64(fac[n])*fiv[m]%P*fiv[n-m]%P; } i64 F(int n,int k,int x){ if(n-x&1)return 0; return C(k,x)*C(k-1+(n-x>>1),k-1)%P; } int main(){ scanf("%d%d%d%d%lld",&n,&m,&a,&b,&s); iv[1]=1; int mx=(n>m?n:m)*2+7; for(int i=2;i<=mx;++i)iv[i]=i64(-P/i)*iv[P%i]%P; fac[0]=fiv[0]=1; for(int i=1;i<=mx;++i){ fac[i]=i64(i)*fac[i-1]%P; fiv[i]=i64(iv[i])*fiv[i-1]%P; } for(int i=0,z=n;i<=n;++i,z-=2){ i64 j=(s-i64(i)*m); if(z&&j%z==0){ j/=z; if(j>=0&&j<=m)ans=(ans+F(a,n,i)*F(b,m,j))%P; } } if(n%2==0&&s*2==n*i64(m)){ int i=n/2; i64 v=0; for(int j=0;j<=m;++j)v+=F(b,m,j); ans=(ans+v%P*F(a,n,i))%P; } printf("%lld",(ans+P)%P); return 0; }