题目传送门:点击打开链接
题目要求 矩形四个边都必须至少坐上一个人,并且 坐在矩形的一个角算相邻的两条边都有人坐,问有几种做法?
我们肯定答案为0的情况:1.当k<2。2.n*m<k 这个很好理解
下面 我们发现 符合题意的坐法很难枚举出来,那么我们可以反着来求不符合题意的方法数。他要求边上必须有人 那么我们就可以确定一条边上没有人,正好有四条边,我们接下来再用容斥的公式就可以做了。
但是本题还有一个问题,对于组合数取模的问题,如果你直接用杨辉三角求,那没什么问题,但是你如果用求逆元就不可以了,因为1e6+7不是素数,好坑。。。
#include <iostream>
#define rep(i,u,o) for(int i=u;i<=o;++i)
using namespace std;
typedef long long ll;
const int mod=1e6+7;
int n,m,k,cnt=0;
int c[410][410];
void init()
{
rep(i,0,400)
{
rep(j,0,i)
{
if(!j||j==i)
c[i][j]=1;
else
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
}
void solve()
{
cout<<"Case "<<++cnt<<": ";
if(k<2||n*m<k)
cout<<0<<endl;
else
{
ll ans=0;
int e=1<<4;
rep(i,1,e-1)
{
int cnt=0;
int n1=n,m1=m;
rep(j,0,3)
{
if((1<<j)&i)
{
++cnt;
if(j%2) // 这里我给四条边标号 左0,上1,右2,下3 那么当cnt为偶数 左右 两条边减去 cnt为奇数同理
--n1;
else
--m1;
}
}
if(cnt&1)
ans=(ans+c[n1*m1][k])%mod;
else
ans=(ans-c[n1*m1][k])%mod;
}
cout<<(c[n*m][k]-ans+mod)%mod<<endl;
}
}
int main(int argc, const char * argv[])
{
int t;
init();
cin>>t;
while(t--)
{
cin>>n>>m>>k;
//cout<<c[n*m][k]<<endl;
solve();
}
return 0;
}