遞推:HDU 不容易系列之(4)——考新郎

Problem Description
國慶期間,省城HZ剛剛舉行了一場盛大的集體婚禮,爲了使婚禮進行的豐富一些,司儀臨時想出了有一個有意思的節目,叫做"考新郎",具體的操作是這樣的:
在這裏插入圖片描述

首先,給每位新娘打扮得幾乎一模一樣,並蓋上大大的紅蓋頭隨機坐成一排;
然後,讓各位新郎尋找自己的新娘.每人只准找一個,並且不允許多人找一個.
最後,揭開蓋頭,如果找錯了對象就要當衆跪搓衣板…

看來做新郎也不是容易的事情…

假設一共有N對新婚夫婦,其中有M個新郎找錯了新娘,求發生這種情況一共有多少種可能.

Input
輸入數據的第一行是一個整數C,表示測試實例的個數,然後是C行數據,每行包含兩個整數N和M(1<M<=N<=20)。

Output
對於每個測試實例,請輸出一共有多少種發生這種情況的可能,每個實例的輸出佔一行。

Sample Input
2
2 2
3 2

Sample Output
1
3

思路:錯排+組合

錯排公式:
a[n]=(n-1)*(a[n-1]+a[n-2])
徹底搞懂錯排公式(不懂看這個叭)

組合:
找出N個新郎中的M個新郎選錯共有幾種,即CNM。
公式如下:(只需要看第二個,第一個是排列公式)
在這裏插入圖片描述
組合數的定義:從n個不同元素中取出m(m≤n)個元素的所有組合的個數,叫做從n個不同元素中取出m個元素的組合數。用符號 C(n,m) 表示

#include<bits/stdc++.h>
using namespace std;
long long a[25];

long long c(int N,int M) //求組合數 
{
	long long sum1=1,sum2=1,sum3=1;
	for(int i=1;i<=N;i++)
	sum1=sum1*i;         //sum1爲 N! 
	for(int i=1;i<=N-M;i++)
	sum2=sum2*i;         //sum2爲 (N-M)! 
	for(int i=1;i<=M;i++)
	sum3=sum3*i;         //sum3爲 M! 
	return sum1/(sum2*sum3);
}

int main()
{
    int C;
    cin>>C;
    a[1]=0;
    a[2]=1;
    for(int i=3;i<=20;i++)
    a[i]=(i-1)*(a[i-1]+a[i-2]); //錯排 
    
    while(C--)
    {
    	int N,M;
    	cin>>N>>M;
    	cout<<c(N,M)*a[M]<<endl;
	}
	return 0;
}

遞推算法總結:

遞推算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章