题目:http://uva.onlinejudge.org/external/118/11806.pdf
题意:给定n*m的棋盘和k个一样的石头,最上面和最下面一行,最左边和最右边一列必须放石头,问有多少中方案数。
分析:容斥原理。设最上面一行不放石头的方案为集合A,最下面一行不放的方案为集合B,最左边不放的方案为集合C,最右边放的方案为集合D,全集为S。那么答案就是|S|-|A∪B∪C∪D|,求|A∪B∪C∪D|直接用容斥原理就好。算组合数用杨辉三角递推。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
#define MOD 1000007
LL C[401][401];
void yhsj()
{
LL i,j,k;
for(i=0;i<=400;i++)
{
C[i][0]=1;
C[i][i]=1;
}
for(i=2;i<=400;i++)
for(j=1;j<i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%1000007;
}
int main()
{
yhsj();
int ncase,Case=1;
LL i,j,ans,m,n,k,cnt,a,b;
scanf("%d",&ncase);
while(ncase--)
{
cin>>m>>n>>k;
if(m>n)
swap(m,n);
ans=0;
for(i=1;i<(1<<4);i++)
{
cnt=0;
a=m;
b=n;
if(i&(1<<0))
{
cnt++;
a--;
}
if(i&(1<<1))
{
cnt++;
a--;
}
if(i&(1<<2))
{
cnt++;
b--;
}
if(i&(1<<3))
{
cnt++;
b--;
}
if(cnt&1)
ans=(ans+C[a*b][k]+MOD)%MOD;
else
ans=(ans-C[a*b][k]+MOD)%MOD;
}
printf("Case %d: ",Case++);
cout<<(C[m*n][k]+MOD-ans)%MOD<<"\n";
}
return 0;
}