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 
[submit]
[forum]
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;
} 












你可能感兴趣的:(ACM,sgu,组合数)