1. 程式人生 > >想做只整天擼程式碼的程式狗

想做只整天擼程式碼的程式狗

問題描述:
有n種物品,第i種物品有ai個。從這些物品中取m個,有多少種取法,求出方案數 模上M的餘數。

Sample input:

n = 3;
m=3;
a = {1,2,3};
M = 10000;

Sample output:

6 (0+0+3,0+1+2,0+2+1,1+0+2,1+1+1,1+2+0)

該題採用動態規劃。
其中有一個思想讓我感觸很深:

dp[i+1][j] := 前i種物品中取出j個物品的組合總數

那麼對於dp[i+1][j] 其中的每種取法都可以拆分為前i-1種物品取j-k件,第i種物品取k件、
那麼
dp[i+1][j] =min(j,ai)k=0dp

[i][jk]
做題的時候經常遇到這種公式,而怎麼把他轉換成動態方程,卻沒什麼思路,但是看了該題,終於有了點思路,那就是把上邊的求和公式轉變成另一個dp陣列。

即:min(j,ai)k=0dp[i][jk] = min(j1,ai)k=0dp[i][j1k] + dp[i][j] - dp[i][j-1-ai]

注意,該公式分兩種情況,一個是j-1ai時,另一個即為小於時。

那麼由此得到

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

而在寫程式碼的時候,可能遇到得到的dp數為負數,因為其中有減法運算,所以有減法運算的時候,在末尾加上M 然後再模上M,這樣能確保得到的結果不會出現負數。