組合數學之計數DP


計數類 \(DP\) 在組合計數中是一類十分常用的算法,下面筆者以一些例題作為講解,一來自己復習,二來可以幫助提升對計數題的思維與感受,就計數問題而言,多做這類題目才會找到感覺,其中會插入一些二項式反演的內容,也是和計數息息相關的。

這些題目,關鍵在於理解,而不在於實現的代碼,所以筆者建議在做這一類題目時,不用去實現代碼,理解思想即可,既能提升思維,又節約時間,這里總結了一些比較好的計數題目。

做計數類問題,一般要考慮上一狀態與當前要計算的狀態之間的對應關系,當前的狀態必然是從上面的某狀態形成的局面加上一部分比較可計算的東西得來的。

\(DP\) 轉移方程一定要深刻理解,也要先嘗試自己推,不過可以先看前面的一些例題,再去自己思考其他題目。

求組合數的幾種方法:
\(1.\) 階乘逆元法, \(O(n)\) 預處理, \(O(1)\) 查詢 \(C_n^m\) ,因為預處理逆元要用到快速冪加上費馬小定理,使用條件即費馬小定理的使用條件,\(gcd(a,p)=1\)\(p\) 是素數,這是最常用的方法,一般都不會給出違反費馬小定理的數據。

\(2.\) \(Lucas\) 定理法,\(C_n^m\) \(mod\) \(p\) = \(C_{n/p}^{m/p}*C_{n\%p}^{m\%p}\%p\)

\(3.\) 定義法,不講了。

CQOI2011 放棋子

題意

在一個 \(n\)\(m\) 列的棋盤里放 \(c\) 種顏色的棋子,使得每個格子最多放一個棋子,且不同顏色的棋子不能在同一行或者同一列,有多少種方法?

如圖,左圖為合法,右圖為不合法。
image

Solution

首先這樣考慮,由於相同顏色的棋子會直接占領某些行和某些列,導致這些行和列組成的那些位置不能再放入其他顏色的棋子,所以每種棋子擺放的方案是相對獨立的,會獨立地占領一塊區域,而這些區域的划分依據則是完整的行與完整的列。

那么我們就設 \(f[i][j][k]\) 表示前 \(k\) 種顏色填入任意 \(i\)\(j\) 列之中(這類題都可以這么設),也即它們占領了 \(i\)\(j\) 列,但這些被占領的完整行列可以是任意選取的。

考慮怎么轉移,自然的想法是枚舉當前的第 \(k\) 種顏色占領多少行多少列,那肯定就需要考慮當前,於是又設 \(g[i][j][k]\) 表示剛好某種顏色的 \(k\) 枚棋子放入任意的 \(i\)\(j\) 列。

\(f[i][j][k]=\sum_{l=0}^{i-1} \sum_{r=0}^{j-1} f[l][r][k-1]*g[i-l][j-r][num[k]]*C_{n-l}^{i-l}*C_{m-r}^{j-r}\)

其中 \((i-l)(j-r) \ge num[k]\) ,原因是留出的空位一定要比那種顏色的棋子總數多,這樣才放得下。

這里其實枚舉的是前 \(k-1\) 種顏色放了多少行多少列,和上面提到的枚舉當前是等價的,方案是對應的,那么當前就剩下 \(i-l\) 行和 \(j-r\) 列了,又因為任意選,所以再乘上兩個組合數即可。

我認為比較容易出錯的是 \(l\) 要從 \([0,i-1]\)\(r\) 要從 \([0,j-1]\) ,想一下,第 \(k\) 種顏色必然占據至少一行和一列,而放第一種顏色時,棋盤上沒有棋子,所以從 \(0\) 開始。

答案就是 \(\sum_{i=1}^n \sum_{j=1}^m f[i][j][c]\)

筆者認為這題比較難的是想出這個狀態,方程是比較好寫的。

[SCOI2005] 掃雷

題意

\(n*2\) 的棋盤里面,給定一列掃雷的數字,求有多少種雷的分布方式?

Solution

\(f[i][1/0][1/0]\) 表示考慮前 \(i\) 位的填數,當前這一位是否放,下一位是否放的方案數。

那么每一位只有 \(1.2.3\) 三種可能的數字,分類討論即可。

如果填的 \(1\) 個數超過 \(a_i\) ,那這個狀態的 \(DP\) 數組賦值 \(0\) 即可。

下面以 \(a_i=2\) 為例:

\(f[i][1][1]=f[i-1][0][1]\)

\(f[i][1][0]=f[i-1][1][1]\)

\(f[i][0][1]=f[i-1][0][1]\)

\(f[i][0][0]=0\)

打下草稿就會發現, \(i\) 階段的方案數唯一對應着一種上一階段 \(i-1\) 的方案數,正確性顯然,

這個題學到的一個 \(trick\) 就是,設計狀態時,如果只設計出包含當前和之前某狀態的話,不好進行轉移,那么不妨把接下來的狀態加入方程。

例如本題,因為當前格子的數由三個位置決定,故需要考慮下一位,同時, \(i-1\) 某些狀態也直接對應一部分 \(i\) 狀態,加上即可。

[AHOI2009] 中國象棋

題意

在一個 \(n\)\(m\) 列的棋盤上,讓你放若干個炮(可以是 \(0\) 個),使得沒有一個炮可以攻擊到另一個炮,請問有多少種放置方法?

也就是說,每行每列最多兩個炮。

Solution

這題感覺和第一個例題挺像的。

考慮到最多兩個炮,於是在狀態里把個數表示出來,設 \(f[i][j][k]\) 表示前 \(i\) 行,有 \(j\) 列一個炮,有 \(k\) 列兩個炮。

則有 \(m-j-k\) 列沒放,分別考慮當前行放置 \(0,1,2\) 個炮的情況,分類討論。

這樣的話,行的限制在轉移時枚舉得以滿足,列的限制在狀態中滿足。

轉移方程如下:

當前行放 \(0\) 個棋子:
\(f[i][j][k]=f[i-1][j][k]\)

當前行放 \(1\) 個棋子:
\(f[i][j][k]=f[i-1][j-1][k]*(m-j-k+1)+f[i-1][j+1][k-1]*(j+1)\)

理解一下,其實就是考慮了這個炮放在之前沒有炮的地方還是有一個炮的地方。

當前行有 \(2\) 個炮,方法也是類似,答案就是 \(\sum_{l=0}^m\sum_{r=0}^mf[n][l][r]\) ,其中 \(l+r \le m\)

當前狀態的炮的分布,與上一狀態的炮的分布十分相關,這題感覺也是狀態較為難設,方程比較好寫。

[CF559C] Gerald and Giant Chess

題意

給定一個 \(H*W\) 的棋盤,棋盤上只有 \(N\) 個格子是黑色的,其他格子都是白色的。在棋盤左上角有一個卒,每一步可以向右或者向下移動一格,並且不能移動到黑色格子中。求這個卒從左上角移動到右下角,一共有多少種可能的路線。

Solution

先總結一個常用結論,如果不考慮不能走的限制,那么從起點走到點 \((x,y)\) 的路線條數為 \(C_{x-1+y-1}^{y-1}\),為方便表達,我們記作 \(G(x,y)\) , 證明不在此贅述。

接下來顯然是考慮容斥,用總的路線條數減去通過了黑色格子的不合法路線條數。設 \(f[i]\) 表示從起點走到第 \(i\) 個黑色格子,且中途不經過其他黑色格子的方案數。

那顯然, \(f[i]=G(x_i,y_i)-\sum_{j=1}^nf[j]*G(x[i]-x[j]+1,y[i]-y[j]+1)\) ,其中 \(x[j]\le x[i]\)\(y[j]\le y[i]\)

意思就是,先走到之前某一個黑色格子,再任意走路線,保證這個黑色格子是第一次經過的黑色格子,這樣就不重不漏地划分了狀態。

利用已經求好的一些數據進行遞推,這也是 \(DP\) 的一大妙處吧。

[POJ1737] Connected Graph

題意

\(𝑁\) 個節點的無向連通圖有多少個,節點有編號,編號為 \([1,n]\)

Solution

圖計數的經典問題,雖然現在似乎不怎么考圖計數的問題,但思路是值得學習的,這題也有很多地方值得深究下去,下面會提及一些。

就還是那個套路,直接計數不好做,考慮容斥,數出不合法方案數。

\(f[i]\) 表示 \(i\) 個點形成的無向連通圖個數,顯然總數是 \(2^{\frac{n(n-1)}{2}}\)

轉移只需枚舉 \(1\) 號點所在的連通塊大小,剩下的邊可以任意連接,只是不與枚舉的連通塊連邊。

想一下,為什么要加上 \(1\) 號點的限制而不是直接說成,固定一個大小為 \(i\) 的連通塊?

因為這樣存在算重的可能,如果按照這種方式DP的話,會出現下面這些情況。

假定先固定一個大小為 \(2\) 的連通塊,剩下包含 \(1,2,3\) 的連通塊。
再枚舉到固定大小為 \(3\) 時,剩下包含 \(4,5\) 的連通塊。
image

很明顯,這兩種情況是同一個圖,如果只定義出連通塊大小,不能避免這種算重的情況。

所以要想辦法做到不重,這時候我們就以 \(1\) 號點作為划分標准,其實任取一個點作為划分標准都可以,同時也可以發現,之前那個出錯的定義是比較模糊的,而將一個點加入限制后,就可以很好地解決重復的問題了。

所以就可以寫出轉移方程了,方程網上到處都是,我覺得也不必再寫了,但是為何要設成這樣的狀態,在我看到的范圍內,是沒有題解講到的,更需要分析出這一點。

以上題為止,是 \(NOIP2021\) 之前記錄的題目,然而今年的 \(T2\) 就是一道計數 \(DP\) ,還是很有幫助的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM