uva 11806 Cheerleaders

//    uva 11806 Cheerleaders
//
// 题目大意:
//
// 给你n * m的矩形格子,要求放k个相同的石子,使得矩形的第一行
// 第一列,最后一行,最后一列都必须有石子.
//
// 解题思路:
//
// 容斥原理,我们这样考虑,如果只是n * m放石子,那么最后的结果
// 就是C(n*m,k).我们设A为第一行不放石头的总数,B为最后一行不放石子
// 的总数,C为第一列不放石子的总数,D为最后一列不放石子的总数.则问题
// 转化为在全集S中,求不在A,B,C,D部分的解.则答案为S - | A | - | B |
// - | C | - | D | + | A ^ B|......用一个二进制枚举状态,统计就可以了
//
// 感悟:
//
// 这道题,开始的时候,从正面做,看减去什么,但是最后都是把自己脑子搞糊涂
// 了,不知道自己在干什么,最后,就没有最后了,每次做题,都是这种感觉,看到解答
// 的时候,我才恍然大悟,原来可以这样啊,自己缺乏抽象思维,缺乏转换问题的思维
// 多说也没什么用,继续加油吧!FIGHTING #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> using namespace std; typedef long long ll; const int MAX_N = ;
const ll MOD = ;
ll C[MAX_N][MAX_N];
int n,m,k;
void init(){
C[][] = ;
for (int i=;i<MAX_N;i++){
C[i][] = C[i][i] = ;
for (int j=;j<i;j++)
C[i][j] = (C[i-][j-] + C[i-][j])%MOD;
}
} void input(){ scanf("%d%d%d",&n,&m,&k);
ll sum = ;
for (int S=;S<;S++){
int b = ,r = n,c = m;
if(S & ){
r--;
b++;
}
if (S & ){
r--;
b++;
}
if (S & ){
c--;
b++;
}
if (S & ){
c--;
b++;
}
if (b & )
sum = (sum + MOD - C[r * c][k])%MOD;
else
sum = (sum + C[r * c][k])%MOD;
}
cout << sum << endl;
} int main(){ int t;
init();
//freopen("1.txt","r",stdin);
scanf("%d",&t);
int kase = ;
while(t--){
printf("Case %d: ",kase++);
input();
}
}
上一篇:ubuntu 下安装eclipse &java环境配置


下一篇:LN : leetcode 292 Nim Game