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);
}
}