計數DP 多重組合數問題

2022-02-12 21:55:17 字數 1658 閱讀 1296

多重集組合數,有\(n\)種物品,第 i 種有\(a_i\)個。不同種類的物品可以互相區分但是相同的種類的無法區別。從這些物品中取\(m\)個有多少種取法。

限制條件

\(1 \leq n \leq 1000\)

\(1 \leq m \leq 1000\)

\(1 \leq a_i \leq 1000\)

\(2 \leq m \leq 10000\)

這是乙個比較經典的計數dp問題,我們設dp[i+1][j] := 從前i種物品中取出j個的組合總數。暴力法思維量較小,應用遞推。我們可以把從前\(i\)種物品取\(j\)個,劃分為:從前\(i - 1\)種物品中取\(j-k\)個,從剩下的第\(i\)種物品裡取剩下的\(k\)個。則遞推式可以表示為:

\[dp[i+1][j] = \sum_^}dp[i][j-k]

\]但是利用這個遞推式進行計算的時間複雜度為\(\mathcal\),根據限制條件,該演算法時間複雜度過高,需要進行優化。

我們對遞推式進行優化,優化後的結果如下,下面將闡明如何得到這個遞推式的:

\[dp[i+1][j] = dp[i + 1][j - 1] + dp[i][j] - dp[i][j - 1 - a_i]

\]分兩種情況:

這時候\(dp[i + 1][j - 1]\)的k的取值範圍是\([0, j - 1]\):

\[dp[i + 1][j - 1] = dp[i][j-1] + dp[i][j-2] + \cdots + dp[i][1] + dp[i][0]

\]又因為\(a[i] > j - 1 \rightarrow a[i] \ge j\),這時k的取值範圍是\([0, j]\):

\[dp[i+1][j] = dp[i][j] + dp[i][j - 1] + \cdots + dp[i][1] + dp[i][0]

\]可以發現\(dp[i+1][j]與dp[i+1][j-1]\)之間只差乙個\(dp[i][j]\)可以用如下圖表示:

這時,將式子進行展開得到:

\[\left\

xdp[i+1][j] = dp[i][j] + dp[i][j-1] + \cdots + dp[i][j-a[i]] \\

dp[i+1][j-1] = dp[i][j-1] + \cdots + dp[i][j-1-a[i]] \\

\end\right.

\]用影象進行表示如下:

因此,可以證明上述表示式成立。

核心**如下:

int n, m;

int a[max_n]

int dp[max_n][max_m]

void solve()else dp[i + 1][j] = dp[i + 1][j - 1] + dp[i][j];

} }}

經典例題:poj3046 - ant countin

多重組合數 計數類DP

題目 有n種物品,第i種物品有p i 個,不同種類的物品可以相互區分,同種類的物品不能相互區分。從這些物品種取出m個,有多少種取法,答案對mod取模。思想 dp i j 表示前i種物品,一共拿了j個物品的方案數。為了得到dp i j 那麼可以從前i 1種物品取j k個,再從第i種物品取k個即可 下面...

計數dp 劃分數 多重集組合數

劃分數 把n個無區別的物品劃分成不超過m組。dp i j j的i劃分的總數。dp i j dp i j i dp i 1 j 即 將j個物品分成i份,有兩種情況 每份劃分都大於等於1 dp i j i 存在有乙份以上用0劃分dp i 1 j int main cout 0 多重集組合數 n種物品,第...

多重集組合數問題

參考 題目 有n種物品,第i種物品有a個.不同種類的物品可以互相區分,但相同種類的無法區分.從這些物品中取出m個,有多少種取法?求出數模m的餘數.例如 有n 3種物品,每種a 個,取出m 3個,取法result 6 0 0 3,0 1 2,0 2 1,1 0 2,1 1 1,1 2 0 dp i j...