關於錯排公式以及擴充套件的一些小結論
錯排問題
存在一個排列 \(\{P_i\}\) ,求有多少個排列 \(\{S_i\}\) 滿足 \(\forall P_i \not = S_i\) 。
錯排公式
令 \(f(n)\) 為有 \(n\) 個元素的錯排個數,顯然 \(f(1) = 0, f(2) = 1\) 。
遞推公式
我們會有一個遞推公式:
\[
f(n) = (n - 1)(f(n - 2) + f(n - 1))
\]
考慮新加進來一個元素,肯定不能放到它原來的位置,那麼就是放到其他 \(n - 1\) 個位置中的一個。然後考慮另外一個被佔位置的元素,如果它填到當前這個位置那麼會剩下 \(n - 2\) 需要錯排那麼就是 \(f(n - 2)\)
,不填到當前這個位置那麼就剩下所有數都一起錯排 就是 \(f(n - 1)\) 。
容斥原理
這個顯然是滿足要求的一個計數,那麼我們就可以列舉“犯了幾個錯誤”,也就是有幾個會在原位。
\[ f(n) = \sum_{i=0}^{n} (-1)^{i} \frac{n!}{i!} \]
錯排擴充套件
我們在之前那個問題上擴充套件一點,我們可以使得其中 \(k\) 個不存在限制。(也就是這個 \(k\) 個位置可以不滿足 \(P_i \not = S_i\) )
動態規劃
這個可以用一個神奇的 \(dp\) 去計數,令 \(dp_{i, j}\) 為前 \(i\) 個數,有 \(j\) 個不存在限制。
顯然對於 \(j = 0\) 的時候我們可以和錯排一樣轉移:
\[
dp_{i, 0} = (i - 1) (dp_{i - 1, 0} + dp_{i - 2, 0})
\]
那麼對於 \(j \ge 1\) 的時候考慮新填一個元素造成的局面:
\[
dp_{i, j} = dp_{i - 1, j - 1} + dp_{i, j - 1}
\]
前面就是新填的元素放到自己位置,那麼就和 \(dp_{i - 1, j - 1}\) 的局面是一樣的了,後面就是放到其他任意一個位置那麼不難發現這個和 \(dp_{i, j - 1}\) 的局面是一樣的。
這樣就可以結束這個擴充套件問題了。(注意前面邊界問題就行了)
組合數學
其實應該可以更優秀地解決這個問題,因為可以發現 \(dp_{i, j}\) 和 \(\displaystyle {j \choose i}\) 的遞推形式是一樣的,所以我們可以 \(O(n)\) 推出第一行並且預處理階乘及其逆元,那麼我們可以用一個組合數直接算上去就行了。
至於是否有更好的實現,我並不是很清楚。。。
ps: 本文來自 zhou888 在今天考試中推的神奇 \(dp\) ,很有啟發~