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;
}
遞推算法總結: