【hdu 1521】【标准的指数型母函数】排列组合【求多重集的排列数】

来源:互联网 发布:JAVA在数据库创建表 编辑:程序博客网 时间:2024/05/16 08:14

传送门:http://acm.split.hdu.edu.cn/showproblem.php?pid=1521

描述:

排列组合

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3755    Accepted Submission(s): 1572


Problem Description
有n种物品,并且知道每种物品的数量。要求从中选出m件物品的排列数。例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB","BA"两种。
 

Input
每组输入数据有两行,第一行是二个数n,m(1<=m,n<=10),表示物品数,第二行有n个数,分别表示这n件物品的数量。
 

Output
对应每组数据输出排列数。(任何运算不会超出2^31的范围)
 

Sample Input
2 21 1
 

Sample Output
2
 

Author
xhd
 

Recommend
xhd   |   We have carefully selected several similar problems for you:  2152 2110 1584 1716 1571  

题意:

求多重集的排列数


思路:


标准的指数型母函数题目,只要是知道如何避免重复的问题,那就是除以阶乘,

这个在高中的时候排列组合中已经学到过,不过这个题目还是要注意下精度问题。

推荐资料:http://www.wutianqi.com/?p=2644 和http://www.wutianqi.com/?p=596


代码:

#include <bits/stdc++.h>using  namespace  std;#define rep(i,k,n) for(int i=k;i<=n;i++)double c1[15], c2[15];double fac[15];int val[15];int n, m;void init(){  fac[0] = 1.0;  rep(i, 1, 10){    fac[i] = fac[i - 1] * i;  }}void solve(){  rep(i, 0, m)    c1[i] = c2[i] = 0.0;  rep(i, 0, val[0])    c1[i] = 1.0 / fac[i];  rep(i, 1, n - 1){    rep(j, 0, m)      for(int k = 0; k <= val[i] && j + k <= m; k++)        c2[j + k] += c1[j] / fac[k];    memcpy(c1, c2, sizeof(c1));    rep(j, 0, m)      c2[j] = 0.0;  }}int  main(){  init();  while(~scanf("%d%d", &n, &m)){    rep(i, 0, n - 1)      scanf("%d", &val[i]);    solve();    printf("%.0lf\n",c1[m] * fac[m]);  }  return 0;}



0 0