大概是組合計數問題的基礎,因此稍微寫一下。
或者說,嘗試復習,發現自己都不會了,所以應該寫一下。
約定
這一類問題都可以在問題確定是,用兩個參數 \(n,r\) 來描述。其中 \(n\) 表示球數, \(r\) 表示盒數。
為了方便描述,以下用一串二進制碼表示問題的狀態。例如 0101
:
- 第一位表示球是否相同。
0
表示相同,1
表示不同; - 第二位表示盒是否相同。
0
表示相同,1
表示不同; - 第三位表示球可否不放。
0
表示不可,1
表示可以; - 第四位表示盒可否為空。
0
表示不可,1
表示可以;
因此狀態 0101
就表示:球相同,盒不同,球不可不放,盒可以為空,此時的方案數。
另外,由於有些問題是筆者自己 yy 的,因此正確性存疑,該類問題用 *
標注。如果發現該部分有問題,請及時留言。
11--
球不同、盒不同問題求解的基本途徑是乘法原理。
1101
對於每一個球,它都有 \(r\) 種選擇。由於每個球不同,因此它們的選擇相互獨立,可以直接乘起來。
因此可以得到總方案數為 \(r^n\) ,求解的時間復雜度是 \(O(\log_2n)\) 。
1100
此時盒子不可以為空,但是直接乘法原理我們會得到盒子為空的方案。
注意乘法原理求到的是 " 至少有 0 個盒子為空 " 的方案數。因此不難想到用容斥原理計算。枚舉一下空盒子的數量,就可以方案數是:
求解的時間復雜度是 \(O(r\log_2n)\) 。
在 \(r\) 比較小的情況下,可以 \(O(r)\) 預處理自然數冪,然后求式子,時間復雜度是 \(O(r)\) 。
還可以發現,如果用指數型生成函數描述這個式子,我們可以在 \(O(r\log_2r)\) 的時間批量求出不同的 \(r\) 的解。
你會在之后再見到它的。
1110
這個時候,每個球就多了一個 " 不放 " 的選擇。因此每個球有 \(r+1\) 種選擇。總方案數是 \((r+1)^n\) 。
1111
繼續容斥:
01--
球相同、盒不同問題求解的基本原理是隔板法。
0101
想象 \(n\) 個球排成一列。此時由於盒子是有區別的,因此我們可以將球分成 \(r\) 組,然后第一組放進第一個盒子里,第二組放進第二盒......第 \(r\) 組放進第 \(r\) 盒。因此我們就考慮計算將 \(n\) 個球分成 \(r\) 組的方案數。
顯然這是隔板法的問題。 \(n\) 個球有 \(n-1\) 個縫,從 \(n-1\) 個縫中選出 \(r-1\) 個來插板的方案數是 \(\binom{n-1}{r-1}\) 。
0100
盒子可以為空,因此直接放板子不太對頭。經典的思想是:
我們給每個盒子先放一個 " 假球 " ,這樣總共有 \(n+r\) 個球,並且每個盒子至少有一個球(包括 " 假球 " )。現在再進行隔板法就沒有問題了,方案就是 \(\binom{n+r-1}{r-1}\) 。
0110*
由於球本身沒有區別,因此有球沒放就相當於球的數量變少了。於是就可以直接枚舉球的數量:
這個組合含義也比較顯然。我們同樣可以假想一個盒子,用來裝 " 沒放 " 的球。由於最后這個盒子可以為空,因此總共有 \(n\) 個縫, \(r\) 個板。
注意,盒子不能為空,因此這里不考慮不放球的情況。
0111*
同理易得:
組合意義請自行思考。
注意,盒子可以為空,因此這里需要考慮球都不放的情況。
10--
球不同、盒相同問題求解的基本途徑是第二類斯特林數。
1000
此時直接推導難度比較大,因此我們考慮使用 DP 。
\(f(i,j)\) :有 \(i\) 個球, \(j\) 個盒子,且球不同,盒相同時,球必須放,盒不能空的放球的方案數。
考慮轉移:
最后一個轉移是在討論,在放最后一個球時,是否要新拿盒子。如果新拿一個,就是 \(f(i-1,j-1)\) 。如果不新拿,就從前 \(j\) 個盒子中挑一個放進去。
如果你有所了解,你就會發現,這是第二類斯特林數的遞歸式。這里我們記 \({n\brace r}=f(n,r)\) 。
因此這個問題的答案是 \(n\brace r\) 。
另一種推導方式 是,考慮容斥。我們先給盒子標號,然后枚舉空盒子的數量,最后把標號除掉:
可以發現,后面的容斥式實際就是 1100
的解。因此 1100
的解也可以表述為 \(r!{n\brace r}\) 。
另外,根據這個容斥式也可以使用 NTT 在 \(O(n\log_2n)\) 的時間內求出 \({n\brace 0},{n\brace 1},\dots,{n\brace k}\) 。
補充內容:
斯特林數原本用於描述階乘冪和冪之間的系數關系。第一類斯特林數 \(\begin{bmatrix}n\\k\end{bmatrix}\) 用於描述 \(x^{\underline{n}}\) 展開中 \(x^k\) 的系數,第二類 \(n\brace k\) 用於描述 \(x^n\) 展開中 \(x^{\underline{k}}\) 的系數。以此,冪和階乘冪就可以很方便地進行轉換。
因此可以得到關系式:
\[ x^{\underline{n}}=\sum_{k=0}^n\begin{bmatrix}n\\k\end{bmatrix} x^k\\ x^n=\sum_{k=0}^n{n\brace k} x^{\underline k} \]
當然,兩種數都有其對應的組合含義。
1001
不難想到,可以直接枚舉有球的盒子的數量:
補充說明:
當 \(r=n\) 的時候,問題就變成了,對於大小為 \(n\) 的集合 \(S\) ,將它划分成任意多個非空子集的方案數是多少?
專門有一個數列 \(\{b_n\}\) 來描述它。這類數就叫 " 貝爾數 " 。
簡單推導(考慮第 \(n\) 個元素所在集合大小)可以得出貝爾數的轉移:
\[\begin{aligned} b_n&= \begin{cases} 1&n=0\\ \sum_{k=1}^{n} \binom{n-1}{k-1}b_{n-k}& otherwise \end{cases}\\ b_n&=\sum_{k=0}^n{n\brace k} \end{aligned} \]
可以定義 \(B(x)\) 為貝爾數的指數型生成函數,那么就有 \(B(x)=e^{e^x-1}\) 。具體推導可以參考 洛谷日報 等資料。
1010*
同樣可以枚舉球的數量:
你發現這個式子仍然可以使用 NTT 批量計算。甚至此情況的答案可以直接寫成生成函數形式。
1011*
同樣可以枚舉球和空盒子的數量:
00--
球相同、盒相同問題求解的基本原理是動態規划。
0001
不難發現,此時我們可以直接用每個盒子的球數組成的序列來描述一種方案。
那么我們只枚舉單調不減的序列就好了,也就是說,原問題的等價於求自然數序列的數量:
這里有一個很常見的轉化:枚舉單調不降序列,就相當於枚舉全是 1 的后綴的和。
具體來說,我們可以定義
那么一個單調不降的序列就必然可以拆分成多個 \(s\) 的對應位的和。比如 \(n=4\) 時, \(\{1\ 2\ 3\ 3\}=s_1+s_2+s_3\) 。
於是不難想到一個完全背包:
\(g(i,j)\):在考慮完 \(s_1\sim s_j\) 后,所有后綴的和為 \(i\) 的方案數。
可以得到轉移為:
此時的答案就是 \(g(n,r)\) 。
0000
此時盒子不能為空,我們可以直接給每個盒子分配一個球。當 \(n<r\) 時,答案是 \(0\) 。當 \(n\ge r\) 時,答案就是 \(g(n-r,r)\) 。
0011*
球沒有區別,因此可以直接枚舉數量:
0010*
基本同上:
總結
盒子放球問題雖然模型簡單,但是你可以發現,在 16 種問題中,我們用了 4 種主要的思路:乘法原理、隔板法、斯特林數、動態規划,以及一些常見的技巧,比如容斥。每種主要思路下, 4 個子問題的方法不盡相同。不同主要思路下,處理子問題的限制的方法各自有些相似。
所以說,深入學習盒子放球,對於學習計數是比較有意義的。它的確可以幫助你熟悉一些基礎的計數方法。