Loading

HDU-4248 A Famous Stone Collector 组合数学 DP

HDU 4248

题意:

给定n种颜色不同的石子,每种石头有 num[i] 个。从中取石子,问能够得到多少种不同的序列。

\[n \leq 100,num[i]\leq 100 \]

数据范围比较小,考虑dp

\[dp[i][j]表示选前i种石头,且选的石头总数为j时的不同序列个数 \]

有转移方程

\[dp[i][j] = \sum dp[i - 1][j - k] \cdot \tbinom{j}{k} \quad k\leq num[i] \]

即考虑第i种石头的贡献,也就是第j个中选k个位置给第i种石头。

\[ans = \sum dp[n][i]\quad i \leq 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("");
    }
}
posted @ 2020-08-20 13:20  MQFLLY  阅读(155)  评论(0编辑  收藏  举报