一个优美的容斥原理的实现方式

uva11806
蓝书上的数学基础基本计数方法的最后一题
预处理了C(n,k) (n选择k的排列)
同时巧妙地利用二进制,实现了容斥原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;

const int mod=1e6+7;
const int maxk=500+10;
int C[maxk][maxk];

int (){
memset(C,0,sizeof(C));
C[0][0]=1;
for(int i=0;i<maxk;i++){
C[i][0]=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 T;
cin>>T;
for(int kase=1;kase<=T;kase++){
int n,m,k,sum=0;
cin>>n>>m>>k;
for(int s=0;s<16;s++){
int b=0,r=n,c=m;
if(s&1) {r--,b++;}
if(s&2) {r--,b++;}
if(s&4) {c--,b++;}
if(s&8) {c--,b++;}

if(b&1) sum=(sum+mod-C[r*c][k])%mod;
else sum=(sum+C[r*c][k])%mod;
}
printf("Case %d: %dn",kase,sum);
}
return 0;
}