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_1cdot 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
", res);
}
}