题意:总共有k个啦啦队队员,站在n*m的格子里,每条边至少有一个人,问有几种方法。一个角落可以同时属于两条边。
题解:利用容斥原理和状态压缩。0001,0010,0100,1000分别表示上下左右没人。
则0000表示四条边都有人;0011表示其中上下两边没人。以此类推,共有16种组合方式。
如果上下两边没人那么,高度变为n-2,所以有C((n-2)*m,k)种方式。用这样的方式去计算。
代码:
#include <bits/stdc++.h>
#define mod(x) ((x)%MOD)
using namespace std;
typedef long long ll;
int const MOD = 1e6 + 7;
int const N = 20 + 5;
int const M = 400 + 10;
int T,n,m,k;
int c[M][M];
void Comb(){
for(int i=0;i<M;i++){
c[i][i] = c[i][0] = 1;
for(int j=1;j<i;j++)
c[i][j] = mod(c[i-1][j-1] + c[i-1][j]);
}
}
ll solve(){
ll sum = 0;
for(int i=0;i<(1<<4);i++){
int n1 = n,m1 = m,bit = 0;;
if((i>>0)&1) n1--,bit++;
if((i>>1)&1) n1--,bit++;
if((i>>2)&1) m1--,bit++;
if((i>>3)&1) m1--,bit++;
if(bit&1) sum = mod(sum - c[n1*m1][k] + MOD);
else sum = mod(sum + c[n1*m1][k]);
}
return sum;
}
int main(){
int caser = 0;
cin>>T;
Comb();
while(T--){
cin>>n>>m>>k;
printf("Case %d: %d\n",++caser,solve());
}
return 0;
}