近期學弟在HDU刷題時遇到了關於錯排公式的一些問題,我作為過來人就寫這篇博客來指導他們~~~
錯排的定義:一段序列中一共有n個元素,那么可知這些元素一共有n!種排列方法。假如在進行排列時,原來所有的元素都不在原來的位置,那么稱這個排列為錯排。而錯排數所指的就是在一段有n個元素的序列中,有多少種排列方式是錯排。
遞歸關系:D(n)=(n-1)(D(n-1)+D(n-2)) 特別地有D(1)=0,D(2)=1;
錯排公式:D(n)=(n!)[(-1)^0/0!+(-1)^1/(1!)+(-1)^2/(2!)+(-1)^3/(3!)+......+(-1)^n/(n!)]; 其中n!=n*(n-1)*(n-2)*......3*2*1 特別地有0!=1 1!=1
首先來對遞歸公式進行解釋:
n個不同的元素的一個錯排公式可以分作兩步完成:
第一步:假設我們錯排第一個元素,那么它可以從2~n的位置任意選擇其中的一個,一共是有n-1種選擇。
第二步:錯排其余n-1個元素,也是需要分情況和種類的。因為這需要看第一步的結果,如果第一個元素落在第k個位置上,第二步就需要把k號元素進行錯排,k號元素錯排位置的不同將導致不同的情況會發生:
1.假設k號元素正好落在了第一個元素的位置,那么就可以將第一個元素和第k個元素完全剔除出去,因為相當於只是他們兩者互換了位置,其他元素暫時還沒有發生變動。留下來的n-2元素進行錯排的話,那么我們就可以得到了D(n-2)種 的錯排方式。
2.若k號元素不排到第一個元素的位置,我們可以暫時將現在排在k號位置的第一個元素剔除出去,生下來的就只包含k號元素和原來n-2個的元素了。這時,我們可以將原來的第一個元素的位置看做是現在k號元素的原本位置,因為k號元素不能夠放在原來的位置上,所以就相當於是原來的n-2個元素和k共計n-1個元素進行完全的錯排。那么一共就有D(n-1)種方法。 第二種情況希望大家仔細理解!配一張圖便於理解


那么,我們有根據加法原理,完成第二步有D(n-2)+D(n-1)種方法。
根據乘法原理得到D(n)=(n-1)(D(n-1)+D(n-2)) 。遞推關系解釋完畢。
下面我們來推一下錯排公式
前提假設D(n)=n!N(n) 那么我們根據上面的遞推公式可以得到n!N(n)=(n-1)[(n-2)!N(n-2)+(n-1)!N(n-1)],等式右邊合並一下,我們可以得到
n!N(n)=(n-1)!N(n-2)+(n-1)!N(n-1)同時消去(n-1)!可以得到nN(n)=N(n-2)+N(n-1)
所以就有兩邊同時減去nN(n-1)得到:nN(n)-nN(n-1)=(n-1)N(n-1)+N(n-2)-nN(n-1) 即有:n(N(n)-N(n-1))=-N(n-1)+N(n-2)
即為(N(n)-N(n-1))/(N(n-1)-N(n-2))=(-1)/n;
同理有(N(n-1)-N(n-2))/(N(n-2)-N(n-3))=(-1)/(n-1);
(N(n-2)-N(n-3))/(N(n-3)-N(n-4))=(-1)/(n-2);
......
(N(3)-N(2))/(N(2)-N(1))=(-1)/3;
一共我們得到了n-2個等式,我們可以讓左邊的等式相乘,右邊的等式相乘,因為相消,那么我們可以得到的等式是
(N(n)-N(n-1))/(N(2)-N(1))=(-1)^(n-2)/[n*(n-1)*(n-2)*(n-3)*......4*3] 等式1
又因為(-1)^(n-2)=(-1)^(n) 等式2並且N(2)=D(2)/2!=1/2 N(1)=D(1)/1!=0 所以有N(2)-N(1)=1/2 等式3 將這兩個等式2和3帶入到上面等式1中我們可以得到:
N(n)-N(n-1)=(-1)^n/[n*(n-1)*(n-2)*(n-3)*......*4*3*2] 即為:N(n)-N(n-1)=(-1)^n/n!
所以有N(n)=(-1)^2/2!+...(-1)^(n-1)/(n-1)!+(-1)^n/n! 又因為存在關系D(n)=n!N(n)
得到D(n)=n![(-1)^2/2!+...(-1)^(n-1)/(n-1)!+(-1)^n/n! ] 得證
錯排公式的應用:
n封信放入n個信封,要求全部放錯,共有多少種放法,記n個元素的錯排總數為f(n)
方法一:
某人寫了n封信和n個信封,如果所有的信都裝錯了信封。求所有的信都裝錯信封,共有多少種不同情況。
當N=1和2時,易得解~,假設F(N-1)和F(N-2)已經得到,重點分析下面的情況:
1.當有N封信的時候,前面N-1封信可以有N-1或者 N-2封錯裝。
2.前者,對於每一種錯裝,可以從N-1封信中任意取一封和第 N封錯裝,故=F(N-1) * (N-1)。
3.后者簡單,只能是沒裝錯的那封信和第N封信交換信封,沒裝錯的那封信可以是前面N-1封信中的任意一個,故= F(N-2) * (N-1)。
基本形式:d[1]=0; d[2]=1 遞歸式:d[n]= (n-1)*( d[n-1] + d[n-2])
方法二:
假設有n封信,第一封信可放在(2-n)的任一個信封里,共n-1種放法,設第一封信放在了第k個信封里,若此時第k封信放在了第1個信封里,則只要將剩下的n-2錯排,即f(n-2),若第k封信沒有放在了第1個信封里,可將第1封信的位置看成是“第k個位置”,即將n-1封信錯排,即為f(n-1)
由遞推可得,f(n)=(n-1)*(f(n-1)+f(n-2))
以下是程序實現:
1 #include<stdio.h> 2 int fun(int); 3 int main() 4 { 5 int n,res; 6 printf("input a number:"); 7 scanf("%d",&n); 8 res=fun(n); 9 printf("There are %d cases.\n",res); 10 return 0; 11 } 12 int fun(int n) 13 { 14 if(n==1) 15 return 0; 16 if(n==2) 17 return 1; 18 return (n-1)*(fun(n-1)+fun(n-2)); 19 }
