uva11806
【题意】
n行m列网格放k个石子。有多少种方法?要求第一行,第一列,最后一行,最后一列必须有石子。
【题解】
利用容斥原理。可以转到求“第一行、第一列、最后一行、最后一列没有石子”的方案数。
枚举各个集合的组合时可以借助二进制进行枚举
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,sec,k; int C[510][510]; const int mod=1000007; void pre() { memset(C,0,sizeof(C)); for(int i=0;i<=500;i++) C[i][0]=1; for(int i=1;i<=500;i++) for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;//预处理好所有c } int main() { pre(); scanf("%d",&sec); for(int z=1;z<=sec;z++) { scanf("%d%d%d",&n,&m,&k); int ans=0; for(int i=0;i<16;i++) { int b=0,r=n,c=m; if(i&1){r--;b++;} if(i&2){r--;b++;} if(i&4){c--;b++;} if(i&8){c--;b++;} if(b%2==0)ans=(ans+C[r*c][k])%mod; else ans=(ans+mod-C[r*c][k])%mod; } printf("Case %d: %d\n",z,ans); } }