Lightoj 1005 Rooks

我们不妨设题目中的答案为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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值