全錯位排列是由著名數學家歐拉提出的。
最典型的問題是裝錯信封問題
一個人寫了n封不同的信及相應的n個不同的信封,他把這n封信都裝錯了信封,問都裝錯信封的裝法有多少種?
用a、b、c,d……表示n份相應的寫好的信紙,A、B、C,D……表示寫着n位友人名字的信封,錯裝的總數為記作f(n)。
假設把a錯裝進B中,然后接下來我們可以分為兩種情況,
第一種是b錯裝進了A中,那么問題就變為c,d,e…..n-2個信紙放入C,D,E……n-2個信封時完全放錯時完全裝錯有多少種,有f(n-2)種
第二種是b錯裝進了除A之外的一個信封內,這個時候問題就相當於已知a錯裝進B中,將b,c,d,e…..n-2個信紙放入A,C,D,E……n-2個信封時,b不能放入A中,這里如果我們把A
想象成B0的話,就相當於將b,c,d,e…..n-2個信紙放入B0,C,D,E……n-2個信封時完全放錯,有f(n-1)種
a錯裝進B中,有f(n-1)+f(n-2)種,同樣a錯裝進C中也有f(n-1)+f(n-2)種…..
a錯裝進B中,有f(n-1)+f(n-2)種
a錯裝進C中,有f(n-1)+f(n-2)種
a錯裝進D中,有f(n-1)+f(n-2)種
a錯裝進E中,有f(n-1)+f(n-2)種
a錯裝進F中,有f(n-1)+f(n-2)種
…
所以一共有
f(n)=(n-1)(f(n-1)+f(n-2));
//C++示例代碼 #include <iostream> using namespace std; long long getvalue(int num) { if (num == 1) { return 0; } else if (num == 2) { return 1; } else if (num == 3) { return 2; } else { long long f1 = 1; long long f2 = 2; for (int i = 4; i <= num; i++) { long long t = f2; f2 = (i - 1)*(f1 + f2); f1 = t; } return f2; } } int main() { int num; cout << "input the number of envelop with -1 to end" << endl; while (cin>>num) { if (num == -1) break; long long r = getvalue(num); cout<<"Result:" << r << endl; } return 0; }
相關的題目有
http://acm.hdu.edu.cn/showproblem.php?pid=2049
假設一共有N對新婚夫婦,其中有M個新郎找錯了新娘,求發生這種情況一共有多少種可能.
http://acm.hdu.edu.cn/showproblem.php?pid=2048
神,上帝和老天爺