A,B,C,D 如果是代表上下左右 边界都有人 的话,
边界 = {A,B,C,D} A,B,C,D 还有相交的部分。
根据容斥原理
那答案就是 A+B+C+D-AB-AC-AD-BC-BD-CD+ABC+ABD+BCD-ABCD
但是计算会很麻烦,,
拿A来说
A=C (m,1) + C (m,2) +。。。。 + C (m,min(m,k));
我们知道那个 组合数求和等于 2的 m次方,
但是 min(m,k)让情况复杂,k=min(m,k)的时候 得不出2的 m次方。
所以转换思路,
令,ABCD代表 上下左右边界没有人。
全集=(边界有人)+(边界没人)
边界有人=全集—边界没人
没人就好做多了,如果算不在上边界就是 从 (行数—1)*列 里面 调 k 个格子。
把组合数提前打表。
而且用到了状压的思想,,(我感叹了半个晚上)
代码依然是是偷来的
原文
#include<iostream>
#define ll long long
#define mod 1000007
using namespace std;
int c[405][405]={0};
void zuhe()
{
for(int i=0;i<=404;++i)
{
c[i][0]=1;
c[i][i]=1;
for(int j=1;j<i;++j)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
}
int main()
{
zuhe();
int t,T;
cin>>t;
T=t;
while(t--)
{
int sum=0;
int m,n,k;
cin>>n>>m>>k;
for(int s=0;s<16;++s)
{
int e=m,r=n;
int ans=0;
if(s&1)
{
r--;
ans++;
}
if(s&2)
{
r--;
ans++;
}
if(s&4)
{
e--;
ans++;
}
if(s&8)
{
e--;
ans++;
}
if( ans&1 )
sum=(sum +mod- c[r*e][k])%mod;
else
sum=(sum + c[r*e][k])%mod;
}
cout<<"Case "<<T-t<<": "<<sum<<endl;
}
return 0;
}