白书上的例题,跟LRJ写的基本一样。
注意组合数的递推,这里写错WA了一次。
用到了容斥原理,需要各种情况的组合,用二进制枚举子集,由于是从全集里面扣掉,所以奇变成了减,偶变成了加。感觉还是很厉害。。
取余的时候如果有减法,要记得加一个模,避免出现负数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
#define INF 200000000
#define MOD 1000007
#define MAXN 4000*1005
using namespace std;
int C[505][505];
void Init()
{
for(int i=0; i<=500; ++i)
{
C[i][0]=C[i][i]=1;
for(int j=1; j<i; ++j)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
}
}
int main()
{
int T,kase=0;
scanf("%d",&T);
Init();
while(T--)
{
int N,M,K;
scanf("%d%d%d",&M,&N,&K);
int sum=0;
for(int i=0; i<16; ++i)
{
int a=0,b=M,c=N;
if(i&1)
{
a++;
b--;
}
if(i&2)
{
a++;
b--;
}
if(i&4)
{
a++;
c--;
}
if(i&8)
{
a++;
c--;
}
if(a&1) sum=(sum-C[b*c][K]+MOD)%MOD;
else sum=(sum+C[b*c][K])%MOD;
}
printf("Case %d: %d\n",++kase,sum);
}
return 0;
}