HDU - 4248 A Famous Stone Collector 組合數學 DP
阿新 • • 發佈:2020-08-19
給定n種顏色不同的石子,每種石子有num[i]個。從中取石子,問能得到多少種不同的序列。
n <= 100, num <= 100。
資料範圍比較小,考慮dp
dp[i][j] 表示選前i種石頭,且石頭總數為j時的不同的序列的個數。
轉移方程 dp[i][j] = sum(dp[i - 1][j - k ] * C(j, k)) k <= num[i]。
考慮第i種石頭的貢獻,也就是j個種選k個位置給第i種石頭。
ans = sigma dp[n][i] i <= sum
ll C[10015][105]; void init() { for (int i = 0; i < 10015; i++) { C[i][0] = 1; for (int j = 1; j <= i && j <= 105; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD; } } int num[105]; ll dp[105][10005]; int main() { int n; init(); int kase = 1; while (~scanf("%d", &n)) { ll sum = 0;for (int i = 1; i <= n; i++) num[i] = readint(); memset(dp, 0, sizeof dp); dp[0][0] = 1; for (int i = 1; i <= n; i++) { sum += num[i]; for (int j = 0; j <= sum; j++) { for (int k = 0; k <= num[i] && j >= k; k++) dp[i][j]+= dp[i - 1][j - k] * C[j][k], dp[i][j] %= MOD; } } ll res = 0; for (int i = 1; i <= sum; i++) res += dp[n][i], res %= MOD; printf("Case %d: ", kase++); Put(res); puts(""); } }