SGU - 222 - Little Rooks (组合数)

222. Little Rooks
time limit per test: 0.25 sec.
memory limit per test: 65536 KB
input: standard
output: standard



Inspired by a "Little Bishops" problem, Petya now wants to solve problem for rooks. 

A rook is a piece used in the game of chess which is played on a board of square grids. A rook can only move horizontally and vertically from its current position and two rooks attack each other if one is on the path of the other. 

Given two numbers n and k, your job is to determine the number of ways one can put k rooks on an n × n chessboard so that no two of them are in attacking positions. 

Input

The input file contains two integers n (1 ≤ n ≤ 10) and k (0 ≤ k ≤ n 2). 

Output

Print a line containing the total number of ways one can put the given number of rooks on a chessboard of the given size so that no two of them are in attacking positions. 

Sample test(s)

Input
 
4 4 
Output
 
24 

Author: Andrew Stankevich
Resource: Little Chess Pieces Series, SPb IFMO 2003-2004 Authumn Training Sessions
Date: 2003-10-01











思路:因为是象棋中的车,它可以攻击同一行和同一列的棋子,所以不妨将每个车固定在一列中,这样不会影响到结果(自己想想为什么)

①先考虑n == k的情况

比如n = 3, k = 3

这时有三个车,且棋盘为3行3列,把第i车固定到第i列上,可以得到the numbers of ways,即3*2*1,

可以推广到n*(n-1)*(n-2)*.....*1 (k = n)

②而n > k时,先把棋盘看做n*k网格(n行k列,k个车放到k列上)的,有ans = n*(n-1)*......*(n - k + 1)

再把这个棋盘扩展为n*n网格的,可以发现只是将列数增加到了n而已

现在我们可以从n列中取出k列分给k个数,即组合数C(n, k);

由乘法原理,于是可以得出答案为n*(n-1)*......*(n - k + 1)*C(n, k);(此时对①情况也适用)

③当n < k时输出0




AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;

LL ans;

int main() {
	int n, k;
	while(scanf("%d %d", &n, &k) != EOF) {
		if(k > n) {
			printf("0\n");
		}
		else if(k == 0) {
			printf("1\n");
		}
		else {
			ans = 1;
			for(int i = n; i > n - k; i--) {
				ans *= i;
			}
			ans = ans * ans;
			for(int i = k; i > 1; i--) {
				ans /= i;
			}
			cout << ans << endl;
		}
	}
	return 0;
} 












  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值