我们不妨设题目中的答案为M(n,k),n和k分别对应题目中的n和k。同样的,我们仍然从简单的情况分析。
当k>n时,显然不可能摆放所有的棋子,所以此时M(n,k)=0;
所以我们现在只讨论当k小于等于n时的情况。
当k=1时,我们可以在任意一个位置摆放棋子,所以此时M(n,1)=n^2;
当k=2时,首先假设k小于等于n,我们可以这样想,先在棋盘的n竖列中选取两列,随后,只要两个棋子的“高度”不同(把棋盘看作一个坐标系,选取好竖列后相当于确定了其横坐标,下面我们只需要考察纵坐标即可)就可以记作一种可行方案。那么显然,子问题转化为在高度为n的单元格上有n个棋子,其中只有两个棋子是不透明的,其余棋子为透明棋子。问有多少种排列方式。答案很明显是A(n,2)。在考虑到第一步的答案C(n,2),由分布计数的结论,M(n,2)=A(n,2) * C(n,2)。
/***************************
* Author:fisty
* Data:2014-10-03
* lightoj 1005
* 组合数学
**************************/
#include <cstdio>
#include <cstring>
using namespace std;
int comb[31][31];
void combination(){
for(int i = 0;i <= 30; i++){
comb[i][i] = 1;
comb[i][0] = 1;
}
for(int i = 2;i <= 30; i++){
for(int j = 1; j <= i-1 ;j++){
comb[i][j] = comb[i-1][j] + comb[i-1][j-1];
}
}
}
int main(){
memset(comb, 0, sizeof(comb));
combination();
int t;
int cnt = 0;
scanf("%d", &t);
while(t--){
int n,k;
scanf("%d%d", &n, &k);
printf("Case %d: ", ++cnt);
if(k > n){
printf("0\n");
}else{
long long com = comb[n][k];
long long ans = com * com;
for(int i = 1;i <= k; i++){
ans *= i;
}
printf("%lld\n", ans);
}
}
return 0;
}