多重組合數 計數類DP

2021-10-05 17:14:00 字數 1198 閱讀 8739

題目:有n種物品,第i種物品有p[i]個,不同種類的物品可以相互區分,同種類的物品不能相互區分。

從這些物品種取出m個,有多少種取法,答案對mod取模。

思想:dp[i][j]表示前i種物品,一共拿了j個物品的方案數。

為了得到dp[i][j],那麼可以從前i-1種物品取j-k個,再從第i種物品取k個即可

下面的x[i]替換成p[i]

分2種情況討論:

情況1:j<=x[i]

右邊展開得到的是dp[i-1][0] dp[i-1][1] dp[i-1][2]....dp[i-1][j] 、 把最後一項拿出來,剩下的j-1項求和,但是我們寫成這樣:

,與原來等價,且我們能輕易發現,這就是dp[i][j-1];

也就是 dp[i][j]=dp[i][j-1]+dp[i-1][j];

情況 2:  j>x[i]

右邊展開得到的是dp[i-1][j-x[i]] dp[i-1][j-x[i]+1] dp[i-1][j-x[i]+2]....dp[i-1][j] 、仿照上面的形式,同樣得到乙個求和式(上界取x[i]),

顯然能發現這個式子拆開後,多出一項dp[i][j-1-x[i]],所以最後要減掉,即:dp[i][j]=dp[i][j-1]+dp[i-1][j] - dp[i][j-1-x[i]];

綜上,遞推式為:

if(j >p[i] )

dp[i+1][j] = (dp[i][j] + dp[i+1][j-1] - dp[i][j-1-p[i]] +mod)%mod;

else

dp[i+1][j] = dp[i][j] + dp[i+1][j-1]; 

**模板:

void solve()

cin>>mod;

for(int i=0; i<=n; ++i)

dp[i][0]=1;

for(int i=0; ip[i])

else}}

cout<

}

計數DP 多重組合數問題

多重集組合數,有 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 劃分數 多重集組合數

劃分數 把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種物品,第...

多重排列和多重組合

比如有這樣乙個例子 helloo這個單詞字母排列有多少種方案呢?我們學過無重排列,那我們是不是可以轉化呢?我們把 l o 分別加上下標1,2,那麼就有6個不同的字母了。全排列的個數為6!然後我們在除以重複數字的冗餘度即 6!2 2!這就是多重排列的方案數了。那我們來擴充套件一下 二項式定理 a b ...