Loading

HDU - 1521 排列组合 指数型生成函数

HDU - 1521 排列组合 指数型生成函数

指数型生成函数

指数型生成函数通常用来解决多重集的排列问题

对于一个多重集,其中\(a_1\)重复\(n_1\)次,\(a_2\)重复\(n_2\)次....\(a_k\)重复\(n_k\)次,从中取\(r\)个排列的不同排列数所对应的指数型生成函数为

\[G(x) = (1 + \frac{x}{1!}+\frac{x^2}{2!}+...\frac{x^{n_1}}{n1!})(1+\frac{x}{1!}+\frac{x^2}{2!}+...\frac{x^{n_2}}{n_2!})...(1+\frac{x}{1!}+\frac{x^2}{2!}+...+\frac{x^{n_k}}{n_k!}) \\ = a_0+a_1\cdot x + \frac{a_2}{2!}\cdot x^2 +.... + \frac{a_p}{p!} \cdot x^p \]

其中\(a_i\) 为选出i个物品的排列方法数

注意此题最后乘上阶乘

HDU-1521

题意

\(n\)种物品,并且已知每种物品的数量,要求从种挑选\(m\)件物品的排列数,例如现有 \(A\) ,\(B\) ,从中选两件物品,就有\(\{A,B\}\) ,\(\{B,A\}\) 两种

代码

double fac[15];
double c1[15], c2[15];
int num[15];

void init() {
    fac[0] = 1;
    for (int i = 1; i < 15; i++) fac[i] = fac[i - 1] * i;
}

int main() {
    init();
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        for (int i = 1; i <= n; i++) num[i] = readint();
        memset(c1, 0, sizeof c1);
        memset(c2, 0, sizeof c2);
        c1[0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= num[i]; j++)
                for (int k = 0; k + j <= m; k++)
                    c2[k + j] += c1[k] / fac[j];
            for (int i = 0; i < 15; i++) c1[i] = c2[i], c2[i] = 0;
        }
        double res = c1[m] * fac[m];
        printf("%.0f\n", res);
    } 
}
 
posted @ 2020-08-21 15:38  MQFLLY  阅读(186)  评论(0编辑  收藏  举报