不容易系列之(4)——考新郎--错排公式&&排列组合

来源:互联网 发布:程序员 转行 投资 编辑:程序博客网 时间:2024/06/05 09:04

先看看百度百科:

问题: 十本不同的书放在书架上。现重新摆放,使每本书都不在原来放的位置。有几种摆法?
这个问题推广一下,就是错排问题,是组合数学中的问题之一。考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。 n个元素的错排数记为D(n)。 研究一个排列错排个数的问题,叫做错排问题或称为更列问题。
错排问题最早被尼古拉·伯努利和欧拉研究,因此历史上也称为伯努利-欧拉的装错信封的问题。这个问题有许多具体的版本,如在写信时将n封信装到n个不同的信封里,有多少种全部装错信封的情况?又比如四人各写一张贺年卡互相赠送,有多少种赠送方法?自己写的贺年卡不能送给自己,所以也是典型的错排问题。

推导过程:blabla

最终的推导结果时:D(n) = n! [(-1)^2/2! + … + (-1)^(n-1)/(n-1)! + (-1)^n/n!].
错排公式的原形为D(n),但是当n很大时计算就很不方便。一个供参考的简化后的公式是D(n) = [n!/e+0.5] ,其中e是自然对数的底,[x]为x的整数部分。
这个公式计算的值满足一种规律,而我们在写程序的时候往往就利用这个规律,非常方便
即p[i]=(i-1)*(p[i-1]+p[i-2]);(其中p[1]=0,p[2]=1);


写个例子看一下:


Problem Description
国庆期间,省城HZ刚刚举行了一场盛大的集体婚礼,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样的:
杭电 <wbr>acm <wbr>2049 <wbr>( <wbr>不容易系列之(4)——考新郎 <wbr>)
首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排;
然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个.
最后,揭开盖头,如果找错了对象就要当众跪搓衣板...

看来做新郎也不是容易的事情...

假设一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.

Input
输入数据的第一行是一个整数C,表示测试实例的个数,然后是C行数据,每行包含两个整数N和M(1<=20)。

Output
对于每个测试实例,请输出一共有多少种发生这种情况的可能,每个实例的输出占一行。

Sample Input
2 2 
3 2

Sample Output
3


题解:这个题就是典型的错排问题,不过加了一些要求,就是 n个中有m时错的,所以就要设计排列组合计算;



#include<iostream>

using namespace std;


__int64 Fab(int n){
__int64 ans=1;
for(int i=1; i<=n; i++){
ans*=i;
}
return ans;
}
int main(){
int t;
cin >> t;
__int64 p[21];
p[1]=0;
p[2]=1;
int i;
for(i=3; i<=20; i++){//错排公式 
p[i]=(i-1)*(p[i-1]+p[i-2]);
}
while (t--){
int a,b;
cin >> a  >> b;
cout << Fab(a)/Fab(b)/Fab(a-b)*p[b] << endl;
}
return 0;
}



阅读全文
0 0
原创粉丝点击