LightOJ1005---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 vertically or horizontally from its current position and two rooks attack each other if one is on the path of the other. In the following figure, the dark squares represent the reachable locations for rook R1 from its current position. The figure also shows that the rook R1 and R2 are in attacking positions where R1 and R3 are not. R2 and R3 are also in non-attacking positions.

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

Input

Input starts with an integer T (≤ 350), denoting the number of test cases.

Each case contains two integers n (1 ≤ n ≤ 30) and k (0 ≤ k ≤ n2).

Output

For each case, print the case number and 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. You may safely assume that this number will be less than 1017.

Sample Input

Output for Sample Input

8

1 1

2 1

3 1

4 1

4 2

4 3

4 4

4 5

Case 1: 1

Case 2: 4

Case 3: 9

Case 4: 16

Case 5: 72

Case 6: 96

Case 7: 24

Case 8: 0

每行每列最多只能有1个

先从n行里选k行,再从n列里选k列,然后需要排列一下

如果k>n 答案是0

k≤n: C(n,k)?C(n,k)?n!

/*************************************************************************
    > File Name: LightOJ1005.cpp
    > Author: ALex
    > Mail: [email protected]
    > Created Time: 2015年06月03日 星期三 21时02分45秒
 ************************************************************************/

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#include <set>
#include <vector>

using namespace std;

const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

LL C[33][33];

int main() {
    C[0][0] = 1;
    for (int i = 1; i <= 30; ++i) {
        C[i][0] = C[i][i] = 1;
        C[i][1] = i;
        for (int j = 2; j < i; ++j) {
            C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
        }
    }
    int t, icase = 1;
    scanf("%d", &t);
    while (t--) {
        int n, k;
        scanf("%d%d", &n, &k);
        if (n < k) {
            printf("Case %d: 0\n", icase++);
            continue;
        }
        LL ans = C[n][k] * C[n][k];
        for (int i = 1; i <= k; ++i) {
            ans *= i;
        }
        printf("Case %d: %lld\n", icase++, ans);
    }
    return 0;
}
时间: 2024-10-02 05:40:03

LightOJ1005---Rooks(简单组合数学)的相关文章

LightOJ1005 Rooks(DP/排列组合)

题目是在n*n的棋盘上放k个车使其不互相攻击的方案数. 首先可以明确的是n*n最多只能合法地放n个车,即每一行都指派一个列去放车. dp[i][j]表示棋盘前i行总共放了j个车的方案数 dp[0][0]=1 转移就是从第i-1行转移到第i行,对于第i行要嘛放上一个车要嘛不放,放的话有n-j-1种方法.即dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(n-j-1). 1 #include<cstdio> 2 #include<cstring> 3 using na

BZOJ_1008_[HNOI2008]_越狱_(简单组合数学+快速幂)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1008 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果 相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱. p.s.我真的没有企图概括的必要... 分析 所有情况是m^n,不可能发生越狱的情况是m*(m-1)^(n-1). 最后答案就是: m*(m^(n-1)-(m-1)^(n-1)).做个快速幂就好了. 注意: 1.

POJ 1942 Paths on a Grid(简单组合数学)

Paths on a Grid Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22836   Accepted: 5622 Description Imagine you are attending your math lesson at school. Once again, you are bored because your teacher tells things that you already mastere

【XSY2669】归并排序 树状数组 简单组合数学

题目描述 有一个长度为\(n\)的排列\(n=2^k\),你要把这个数组归并排序.但是在长度为\(2\)的时候有\(\frac{1}{2}\)的概率会把两个数交换(就是有\(\frac{1}{2}\)的概率返回错的结果).有两种操作 \(1\):交换两个数 \(2\):询问排序后的一个位置等于一个数的概率. \(k\leq 16,q\leq {10}^5\) 题解 这个排序有点奇怪.两个数\(a,b(a<b)\)排序后可能是\(ab\)也可能是\(ba\). 观察到\(ab\)会正常排序,而\(

比赛总结

昨天和sduwh打了场友谊赛.题目整体并不难,绝大多数都是基本的数学问题,然而出题的情况极其糟糕.之前就让队友去负责弄数学专题,看来队友也没好好弄,我也没去落实,是我做队长的失职,或许我本身就不适合做队长. 下面结合题目对本次比赛做一个总结: A题:简单数学题.求N!末尾0的个数.N!=2^k1*3^k2*4^k3*5^k4……对于0的产生只能由2和5相乘得到,于是ans=min(k1,k4),而显然k1>=k4,于是ans=k4.对于给定的n,考虑不超过n的数中,有多少个能被5整除,有多少个能

LightOJ-1005 组合数学,组合数水题

LightOJ 1005 题意:n*n的棋盘,放入k个车,要使k个车不相互攻击,有多少种方案. 总结:从n行选出k行(C(n,k)),再从n列选出k列(A(n,k)),即C(n,k)*A(n,k). 注:纠结是C还是A,举个简单的例子,看交换后是否相同. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define F(i,

USTC OJ — 1003 Fibonacci Numbers(组合数学, 简单题)

1. 题目描述 Fibonacci数列定义为: A0 = 0, A1 = 1; An = An-1 + An-2, if n >= 2. 问题:输入一个n( 0 ≤ n ≤ 40 ),计算An. 2. 算法设计 直接利用公式计算即可,时间复杂度O(N),由于数据规模很小,可以选择 先打表,然后对每一个测试数据n,直接输出An: 或者分别对每一个n,计算An. 3. AC Code 1 #include <stdio.h> 2 #define N 41 3 int f[N]; 4 void

Codeforces 223APartial Sums 数论+组合数学

题意很简单,求不是那么好求的,k很大 要操作很多次,所以不可能直接来的,印象中解决操作比较多无非线段树 循环节 矩阵 组合数等等吧,这道题目 也就只能多画画什么 的了 就以第一个案例为主吧 , 3 1 2 3 k我们依据画的次数来自己定好了 下面的每个数表示这个位置的 数由最初的 数组num[]中多少个数加起来得到的 当k为0的时候呢,就是 1 1 1 k为1的时候呢 1 2 3 k为2的时候呢 1 3 6 那么k为3的时候 1 4 10 这里看一下 从数组下标0开始,那么其实就是 C(i +

【组合数学】 06 - 组合设计

计数问题其实只是组合数学中的一小部分,以上也仅仅介绍了比较经典的结论.组合问题复杂多变,它们之间也少有联系,所以把组合数学称作一门学科并不准确.组合难题也会出现在各种益智趣题或竞赛难题中,随随便便就会出现一些未解的难题,所以我们也将止步于此.在结束本课之前,我决定再窥探一下组合问题中的一大类:组合设计.这些问题的关注点在如何布局元素,以满足一些特定要求,它们已然构成了组合学的众多分支. 1. 0-1矩阵 1.1 关联矩阵的秩 有的问题需要在两个集合\(A,B\)间建立联系,如果把\(A,B\)的