错排公式
问题描述:
n封信放入n个信封,要求全部放错,共有多少种放法,记n个元素的错排总数为f(n)
F(n) = ( n -1 ) * ( f(n - 1) + f(n - 2))
详见百科:错排公式 Derangement
疑问
F(N-1)不会包含F(N-2)吗?
直接理解 是f(n) = (n-1) * f (n -1), 第1个数有(n-1)中选择,剩下的就是(n-1)个数的错排了。
看了这个:HDU 2068 RPG的错排(错排公式 + 详解) ,错排公式详解 似懂非懂。
没有什么比实例更直接的了?
考察n=4,根据公式有:
f(4) = 3 * [ f(3) + f(2) ] = 3 * ( 2 + 1 ) = 9
设ABCD为正确排序:
错排有9个:
BADC CDAB DCBA
BCDA CADB DABC
BDAC CDBA DCAB
这三列就是公式里那个3(n-1),即三个情况,这个很容易理解。
重点来看看每种情况下的具体情况,拿第一列来看
对于原排序ABCD,第一情况,第一个书选B
则取B与A交换,得到BACD,如果直接f(n-1), 即求ACD的错排,只能得到BCDA,BDAC; 按照上面的直接理解这就结束了,但是BADC的情况的并没有考虑到,这就是那个f(n-2)。
ADC不是ACD的错排,但是BADC是ABCD的错误。
这就是问题的重点,n = m 时的f(n-1) 和 n =m-1时的f(n)完全不是一种情况。
比如n=4时,确定第一个数后,剩下来的3(n-1)个数ACD 和n=3时的3个数ABC不是同一种情况。
同理对于第二种情况, DAB不是BAD的错排,但是CDAB是ABCD的错排; 对于第三种情况,CBA不是BCA的错排,但是DCBA是ABCD的错排。
总结
所以这次是犯了形而上学的错误,ABCD 看成了 A (BCD),没有考虑到 那个n要在下一阶段,进去搅局:B(ACD), C(BAD), D(BCA)。
补充
简化公式:
D(n) = [n!/e+0.5] ,[]表示只取整数部分,e为自然底数。
C/C++ 中 e的表示:
#include<math.h>
e = exp(1)