题目概述
有
n
个物品,第
解题报告
如果不是组成排列,就是经典的普通型母函数。我们发现无法用普通型母函数表示出“组成排列”这个条件,实际上这是经典的指数型母函数(摘自这里)。
口袋中有白球
2 个,红球 3 个,黄球1 个,任取 3 个作为一个排列,总共有多少种排列?类似地用指数型母函数解决:用
(1+x1!+x22!) 表示取白球 0 个,1 个或者 2 个那么(1+x1!+x22!)(1+x1!+x22!+x33!)(1+x1!) 来表示所有的排列结果。= 1+3x1!+8x22!+19x33!+38x44!+60x55!+60x66!
找到次数为 3 的那一项,系数为
19 ,那么总共有 19 种排列。这道题就按照上面那么做就行了。
示例程序
#include<cstdio> using namespace std; typedef double DB; const int maxn=10; int n,m,num[maxn+5],fac[maxn+5];DB a[maxn+5],b[maxn+5]; int main(){ freopen("program.in","r",stdin); freopen("program.out","w",stdout); fac[0]=1;for (int i=1;i<=maxn;i++) fac[i]=fac[i-1]*i; while (~scanf("%d%d",&n,&m)){ for (int i=1;i<=n;i++) scanf("%d",&num[i]); for (int i=0;i<=m;i++) a[i]=0,b[i]=0;a[0]=1; for (int t=1;t<=n;t++){ for (int i=0;i<=m;i++) for (int j=0;i+j<=m&&j<=num[t];j++) b[i+j]+=a[i]/fac[j]; //a,b需要是实数 for (int i=0;i<=m;i++) a[i]=b[i],b[i]=0; } printf("%.0f\n",a[m]*fac[m]); } return 0; }