UVA - 11806 Cheerleaders(容斥原理)
题意是n*m的格子上,放k个物品,且最上边的一行,最下面的一行,最左边的一行,最右边的一行,必须要放一个,问有多少种方案?
分析:从反方向思考,用总的方案数减去四周都不放的方案数。
用到容斥定理,减去有一边的方案,加上有两边的方案,减去有三边的方案,加上有四边的方案。
然后可以用四位的二进制数表示哪边没有物品,如:1000表示有一边没有棋子的方案
代码如下:
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int MOD=1000007; int C[1010][1010]; void init2() //预处理组合数 { for(int i=0;i<=1000;i++) C[i][0]=1; for(int i=1;i<=1000;i++) { for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD; } } int main() { int n,m,k,a,row,col,sum,t,Case=0; init2(); cin>>t; while(t--) { Case++; cin>>n>>m>>k; sum=0; for(int r=0;r<16;r++) { a=0,row=n,col=m; if(r&1) row--,a++; if(r&2) row--,a++; if(r&4) col--,a++; if(r&8) col--,a++; if(a&1) sum=((sum-C[row*col][k])%MOD+MOD)%MOD; else sum=(sum+C[row*col][k])%MOD; } printf("Case %d: ",Case); cout<<sum<<endl; } return 0; }