切換
舊版
前往
大廳
主題

ZeroJudge - d443: 10497 - Sweet Child Makes Trouble 解題心得

Not In My Back Yard | 2018-10-20 11:10:40 | 巴幣 0 | 人氣 431

題目連結:


題目大意:
給定一正整數 N(N ≦ 800),代表原本有N個物件,編號為 1 ~ N ,排在 1 ~ N 的位置。

求重新排列,使得 N 個物件都不在自己原來的位置上(也就是「錯排」)的方法數為何?

當 N = -1 時,代表輸入結束。



範例輸入:
1
2
3
4
-1



範例輸出:
0
1
2
9



解題思維:
當窮舉方法數的時候,乍看之下可能沒有什麼規律。但是仔細觀察可以發現,一些疑似遞迴的蹤跡。

考慮以下情況,當 N ≧ 3時:
有鑑於第 N 個數字不會排在第 N 個位置,一定會放在1 ~ N-1其中之一。這時,它放的位置假設為 K ,而 K 放的地方有兩種情形。

第一種, K 放在 N 的位置,也就是 N、K 位置互換。那麼,剩下的N-2個數字之原本的位置也就都尚未被占去。因此這個情況等價於 N-2 時的方法數。

第二種, K 沒有放在 N 的位置。由於我們已經把 N 放在 K 的位置,而K絕對不會放在N的位置。我們把放在 K 位置的N拿掉,剩下的物件就像是 N-1 時的情況之排列(K就變成了新的N)。因此等價於 N-1 時的方法數。

又因為N放的時候,可以從1 ~ N-1任意挑一個位置放(也就是K是其中任意數字)。因此K有N-1種可能挑法。

所以, N 的方法數 = (N-1)*(N-1的方法數 + N-2的方法數)。



而又因為N可到800的緣故,因此上述遞迴式的值會增長到突破C++的整數型態上限,為此,我們需要大數運算,詳見這裡




此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作