YT03-遞推求解課後題目-1006 不容易系列之(4)——考新郎-(6.7日-煙臺大學ACM預備隊解題報告)

kewlgrl發表於2015-06-13

不容易系列之(4)——考新郎

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 34   Accepted Submission(s) : 23

Font: Times New Roman | Verdana | Georgia

Font Size:  

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

Author

lcy

Source

遞推求解專題練習(For Beginner)

計141-劉佳琦



思路:

由題意M個新郎都找錯了新娘,可看出這是一道錯排題。但我們並不知道哪M個人是錯排的。

   1.因此,先找到N箇中M個錯排有幾種,N箇中有M個找錯新娘要用到高中所學的排列組合。即              =N!/(M!*(N-M)!)。也就是    =N!/M!/(N-M)!。

    2.然後再求出M個數的錯排個數,遞推關係:f[n]=(n-1)*(f[n-1]+f[n-2])



錯排推導過程

•第一種情況:如果開始有n-1個人都已經完成了錯排(有f(n-1)種可能),第n個人可以通過用自己的新娘去和那n-1個人中的任意一個交換,來實現n個人都錯排。這種情況有(n-1)*f[n-1]種可能;
•第二種情況:如果開始的n-1個人不是都錯排,那麼要想使第n個人與其中一個交換後實現錯排的話就必須滿足兩個條件:
•1.那n-1個人中只有一個人選到了自己的新娘,也就是說有n-2個人都已經錯排了。
•2.第n個人必須和那個選到自己新娘的人去交換,但那個選到自己新娘的人可以是n-1個人中的任意一個。這種情況有(n-1)*f[n-2]種可能。
•其他情況都不能滿足n個人錯排。
•因此遞推關係:f[n]=(n-1)*(f[n-1]+f[n-2])。

#include <iostream>
using namespace std;
int main()
{
    int T,n,m,i;
    long long a[21],b[21];
//測試邊界資料可以發現資料較大要用longlong或者__int64 ,其中a[21]陣列儲存階乘用來做組合運算,b[21]儲存錯排的情況
    a[0] = 1; a[1] = 1,a[2] = 2;
    for(i = 3; i < 21;i++)
        a[i] = a[i-1]*i;
    b[0] = 0;b[1] = 1;b[2] = 1,b[3] = 2;//之前推導的公式是從m=3開始的
    for(i = 4; i < 21;i++)
        b[i] = (i-1)*(b[i-1]+b[i-2]);
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        cout<<a[n]/a[m]/a[n-m]*b[m]<<endl; //n中m個找錯人的可能情況個數(排列組合)乘以m個全都錯了的可能(錯排)就是所要求的
    }
    return 0;
}



相關文章