指数生成函数

指数生成函数

定义:\(F(x)=\sum_{n\ge 0}a_n\frac{x^n}{n!}\)

\(<1,1,1,\cdots>\longrightarrow1+\dfrac{x}{1!}+\dfrac{x^2}{2!}+\dfrac{x^3}{3!}+\cdots=\sum_{n\ge 0}\dfrac{x^n}{n!} = e^x\)

\(<1,p,p^2,\cdots>\longrightarrow1+p\dfrac{x}{1!}+p^2\dfrac{x^2}{2!}+p^3\dfrac{x^3}{3!}+\cdots=\sum_{n\ge 0}p^n\dfrac{x^n}{n!} = e^px\)

加减运算:

\(\begin{aligned} F(x) \pm G(x) & =\sum_{i \geq 0} a_i \frac{x^i}{i !} \pm \sum_{j \geq 0} b_j \frac{x^j}{j !} \\ & =\sum_{n \geq 0}\left(a_n \pm b_n\right) \frac{x^n}{n !} \end{aligned}\)

卷积:

\(\begin{aligned} F(x) & G(x)=\sum_{i \geq 0} a_i \frac{x^i}{i !} \sum_{j \geq 0} b_j \frac{x^j}{j !} \\ & =\sum_{n \geq 0} x^n \sum_{i=0}^n a_i b_{n-i} \frac{1}{i !(n-i) !} \\ & =\sum_{n \geq 0} \frac{x^n}{n !} \sum_{i=0}^n \frac{n !}{i !(n-i) !} a_i b_{n-i} \\ & =\sum_{n \geq 0} \frac{x^n}{n !} \sum_{i=0}^n C_n^i a_i b_{n-i} \end{aligned}\)

\(n=i+j\)

用处:不同于普通生成函数,指数生成函数用来解决多重集排列数问题。

HDU-1521 排列组合:

\(n\) 种物品,每种物品 \(a_i\) 个,问取 \(m\) 个物品的排列数?

设个每种物品中取 \(b_i\) 个,\(0\le b_i\le a_i\)\(m=\sum^n_{i=1}b_i\),对于一组选定的 \(b_i\) 进行排列的方案数为 \(\dfrac{m!}{b1!b2!\cdots b_n!}\)。意思是 \(m\) 的全排列去掉每一组中的重复。

例如取3个A、1个B的排列数为 \(\dfrac{4!}{3!1!}=\dfrac{24}{6}=4\),即AAAB,AABA,ABAA,BAAA。

那么所有满足 \(b_1+b_2+\cdots+b_n=m\) 的排列数之和,即答案。

构造指数生成函数:第1种物品的生成函数为 \(\left(1+\dfrac{x^1}{1 !}+\dfrac{x^2}{2 !}+\cdots+\dfrac{x^{a_1}}{a_{1} !}\right)\),第 \(n\) 种物品的生成函数为 \(\left(1+\dfrac{x^1}{1 !}+\dfrac{x^2}{2 !}+\cdots+\dfrac{x^{a_n}}{a_{n} !}\right)\)

\(\left(1+\dfrac{x^1}{1 !}+\dfrac{x^2}{2 !}+\cdots+\dfrac{x^{a_1}}{a_{1} !}\right)\left(1+\dfrac{x^1}{1 !}+\dfrac{x^2}{2 !}+\cdots+\dfrac{x^{a_2}}{a_{2} !}\right) \cdots\left(1+\dfrac{x^1}{1 !}+\dfrac{x^2}{2 !}+\cdots+\dfrac{x^{a_n}}{a_{n} !}\right)\)

\(\dfrac{x^m}{m!}\) 的系数。

做乘法:\(\dfrac{x^{b_1}}{b_{1} !} \times \dfrac{x^{b_2}}{b_{2} !} \times \cdots \times \dfrac{x^{b_n}}{b_{n} !}=\dfrac{x^{b_1+b_2+\cdots+b_n}}{b_{1} ! b_{2} ! \cdots b_{n} !}=\dfrac{x^m}{b_{1} ! b_{2} ! \cdots b_{n} !}=\dfrac{m !}{b_{1} ! b_{2} ! \cdots b_{n} !} \cdot \dfrac{x^m}{m !}\)

做卷积,所有满足\(b_1+b_2+\cdots+b_n=m\) 的项的系数之和,再乘以 \(m!\),即为答案。

求系数的方法还是累加。需要预处理阶乘。

代码:

int n,m;
int a[11];
double fac[11];
double C[11],D[22];

void init(){//计算阶乘
  fac[0]=fac[1]=1;
  for(int i=2;i<=100;++i)
    fac[i]=fac[i-1]*i;
}
double calc(){
  for(int i=0;i<=m;++i) C[i]=D[i]=0;
  for(int i=0;i<=a[1];++i) C[i]=1.0/fac[i];
  for(int i=2;i<=n;++i){
    //计算x^(j+k)的系数
    for(int j=0;j<=m;++j)
      for(int k=0;k<=a[i];++k)
        D[j+k]+=C[j]/fac[k];
    //转存C,清空D    
    for(int j=0;j<=m;++j)
      C[j]=D[j], D[j]=0;
  }
  return C[m]*fac[m];
}

int main(){
  init();
  while(~scanf("%d%d",&n,&m)){
    for(int i=1; i<=n; ++i)
      scanf("%d",&a[i]);
    printf("%.0lf\n",calc());
  }
  return 0;
}
posted @ 2022-12-27 16:28  Vegdie  阅读(123)  评论(0编辑  收藏  举报