dddsx259

导航

生成函数

生成函数 :

1. 普通生成函数

\((a_n)_{n\in\mathbb{N}}\)的母函数, 也被称作“生成函数(Generating Function)“, 是一种形式幂级数, 其每一项的系数都可以提供关于这个数列的信息.
e.g.

\[G(x)=a_0+a_1x+...+a_kx^k+\dots \]

其中第 \(i\) 项的系数是数列的第 \(i\) 项, 而自变量 \(x\) 的选取不改变这个多项式的意义, 故我们称这种函数为形式幂级数. 如上所示的 \(G(x)\) 是一种较常见而直观的母函数, 被称作“普通生成函数(Ordinary Generating Function, OGF)”

1.1 引子

为理解其意义, 我们举两例子:
第一个较简单, 考虑高中时的生物遗传题, 父母基因型均为Aa, 则子代基因型分布为经典的(1:2:1), 老师通常会用如下的方式为学生说明计算逻辑(以及做题时常用的方法):

\[\begin{aligned} &(A+a)(A+a)\\ &=(AA+Aa+Aa+aa)\\ &=1AA+2Aa+1aa \end{aligned} \]

(这种方法也被称作“配子法”)
如果我们把父母可能产生的配子所携带的基因看作数列的各个项(按出现概率分配出现次数比例), 那么两个配子的结合计算过程就可以看作是两个有限多项式的乘法, 也即:

\[\begin{aligned} &(Ax+a)(Ax+a)\\ &=(AAx^2+Aax+Aax+aa)\\ &=AAx^2+2Aax+aa \end{aligned} \]

第二个, 我们考虑一个组合问题:
我们有 \(n\) 种不同的盒子, 每个盒子中有 \(a_i\) 相同的球, 我们取 \(m>n\) 个球(只考虑组合, 不考虑排列), 那么有多少种取出方案?

不难想到通过DP背包的方法解决(不简化双层的原因是为更好说明其与生成函数的关系):

total_balls = 114514    #球的总数
def dp(n, m, A):
    DP = [[0] * (m + 1) for _ in range(n + 1)]      
    #DP[i][j]表示在所需的球选到第i个时,已经判断了j个球的取舍时的方案数
    DP[0][0] = 1    #初始情况, 什么都不选的话有1种可能
    for i in range(1, n + 1):
        for j in range(m + 1):
            for k in range(min(A[i - 1], j) + 1):
                DP[i][j] += DP[i-1][j-k]
    return DP[n][m]

而我们再考虑另一种考虑的视角:
我们有 \(n\) 个数列, 他们对应 \(n\) 个普通生成函数:

\[G_i(x)=\sum^{a_i}_{i=0}x^i \]

我们将这 \(n\) 个多项式相乘,所得到的结果多项式的第 \(m\) 次项系数即为我们所求方案数.

我们思考一下这两种思考角度的异同, 发现背包dp和多项式乘法的过程是相似的, 都是累计结果的相加.

1.2 OGF的基本运算:

我们考虑两生成函数与其对应的两数列:

\[A(x)\leftrightarrow [a_n], B(x)\leftrightarrow [b_n] \]

  1. 对于两生成函数的和函数, 其对应着两相应数列的和数列

    \[C(x)=A(x)+B(x)\leftrightarrow [a_n+b_n] \]

  2. 对于两生成函数的积函数,其对应着两数列的卷积( \(a*b\) )

    \[A(x)*B(x)\leftrightarrow [c_n=\sum_{i=0}^{n}a_ib_{n-i}] \]

而下面的一种对OGF幂形式的变换卡, 通常能更好的简化运算

1.3 OGF的封闭形式

我们考虑 \(G(x) = \sum^{\infty}_{i=0}x^i\) , 我们发现有:

\[x\cdot G(x) = 1 + G(x) \]

(仅在 \(x\in[-1,1]\) 时成立, 因为仅有此时 \(x^\infty\)收敛)
故:

\[G(x) = \frac{1}{1-x} \]

(也可由等比公式求和看出)
因为生成函数是形式幂级数, 我们并不考虑 \(x\) 的具体取值.
但是考虑改变对 \(x\) 进行一系列变换, 我们可以获得如下一些数列的生成函数:

1.3.2 OGF的封闭形式的一些变形

  1. \(x\) 代换成 \(cx\) , 得到

    \[ G(x)=\frac{1}{1-cx},\leftrightarrow\{1, c, c^2, c^3,...\} \]

  2. \(x\) 代换成 \(x^c\) , 得到

    \[ G(x)=\frac{1}{1-x^c},\leftrightarrow\{1, \overbrace{0,..., 0}^{c-1个}, 1, \overbrace{0,..., 0}^{c-1个}, 1,...\} \]

  3. 分子乘 \(c\)

    \[ G(x) = \frac{c}{1-x},\leftrightarrow\{c, c, c,...\} \]

  4. 分子乘 \(x^c\)

    \[G(x) = \frac{x^c}{1-x},\leftrightarrow\{\overbrace{0,0,...0}^{c个},1,1,1\} \]

  5. 对原式求 \(n\) 阶导:

    \[G'(x)=\frac{1}{(1-x)^(n+1)},\leftrightarrow\{a_k=\binom{k-1}{n-k-1}\} \]

PS.若是1阶导, 则得到 \(\{1,2,3,4,...\}\) 的生成函数.

我们这里给出一个通过生成函数解决实际问题的例子:

1.4 引子-斐波那契数列的封闭形式

也即:求解斐波那契数列(Fibonacci Sequence):

\[F_n=F_{n-1}+F_{n-2} \]

我们设:

\[Fi=1+1x+2x^2+3x^3+\dots \]

其中, 每项系数均为相应的Fibonacci项.
那么我们发现:

\[\begin{aligned} &Fi= &&0 &&+ 1x &&+1x^2 &&+2x^3 +\dots\\ &xFi= &&0 x &&+1x^2 &&+1x^3 &&+ 2x^4\dots\\ &x^2Fi= &&0 x^2 &&+1x^3 &&+1x^4 &&+ 2x^5\dots\\ \end{aligned} \]

显然, 我们能发现:

\[Fi=xFi+x^2Fi+x \]

故有:

\[Fi=\frac{x}{1-x-x^2} \]

这个生成函数的多项式形式我们很难直接想到, 但是不难想到将该二次分式变成多个一次式的相加, 注意到:

\[\frac{x}{1-x-x^2}=\frac{x}{x+\frac{1}{2}+\frac{\sqrt{5}}{2}}-\frac{x}{x+\frac{1}{2}-\frac{\sqrt{5}}{2}} \]

这两个一次多项式均可以转化成两个数列的生成函数
也即, Fibonacci可被写成两个数列的和, 即

\[Fi_n=A_n+B_n \]

其中:

\[A_n=\frac{1}{\sqrt{5}}(\frac{1+\sqrt{5}}{2})^n,B_n=-\frac{1}{\sqrt{5}}(\frac{1-\sqrt{5}}{2})^n \]

因此, 我们引出一般地将多项式的比化成幂级数形式:
根据代数基本定理, 对任意的多项式 \(P(x),Q(x)\) ,分式 \(\frac{P(x)}{Q(x)}\) 都可以简化成上述我们熟知的生成函数, 也即:

\[\frac{P(x)}{Q(x)}=C\cdot \frac{\Pi(1-p_ix)^{d^i}}{\Pi(1-p'_ix)^{d'^i}}=\sum\frac{c_ix^{d_i}}{(1-p_ix)^{d'^i}} \]

1.5 牛顿二项式定理

我们定义广义组合数:

\[\binom{n}{k}=\frac{n\cdot(n-1)\dots(n-k+1)}{k!}, n\in\mathbb{C},k\in\mathbb{N} \]

那么广义的牛顿二项式定理是:

\[(1+x)^\alpha=\sum_{n\ge 0}\binom{\alpha}{n}x^n,\alpha\in\mathbb{C} \]

带入 \(\alpha=-1\) 即得OGF的封闭形式与幂级数形式的转换

我们给出一个更有趣的例子:
1.6 例题:

在许多不同种类的食物中选出 n 个,每种食物的限制如下:
承德汉堡:偶数个
可乐:\(0\) 个或 \(1\)
鸡腿:\(0\) 个,\(1\) 个或 \(2\)
蜜桃多:奇数个
鸡块:\(4\) 的倍数个
包子:\(0\) 个,\(1\) 个,\(2\) 个或 \(3\)
土豆片炒肉:不超过一个。
面包:\(3\) 的倍数个
每种食物都是以「个」为单位,只要总数加起来是 \(n\) 就算一种方案

img

接下来, 我们介绍指数生成函数.

2. 指数生成函数

序列 \(a\) 的指数生成函数 (exponential generating function,EGF) 定义为形式幂级数

\[\hat{F}(x)=\sum_na_n\frac{x^n}{n!} \]

2.1 基本运算:

我们考虑两生成函数与其对应的两数列:

\[A(x)\leftrightarrow [a_n], B(x)\leftrightarrow [b_n] \]

  1. 对于两指数生成函数的和函数, 其对应着两相应数列的和数列

    \[C(x)=\hat{A}(x)+\hat{B}(x)\leftrightarrow [a_n+b_n] \]

  2. 对于两指数生成函数的积函数

    \[\begin{aligned} \hat{C}(x) &=\hat{A}(x)\cdot \hat{B}(x)\\ &=\sum_ia_i\frac{x^i}{i!}\cdot \sum_ib_i\frac{x^i}{i!}\\ &=\sum_i\sum_{j=0}^{i}(\frac{a_j}{j!}\cdot\frac{b_{i-j}}{(i-j)!})x^i\\ &=\sum_i\frac{x^i}{i!}\sum_{j=0}^{i}\binom{i}{j}a_j\cdot b_{i-j}\\ &\leftrightarrow [c_n=\sum_{k=0}^{n}\binom{n}{j}a_k\cdot b_{n-k}] \end{aligned} \]

2.2 封闭形式

基于 \(e^x\)\(x=0\) 处的泰勒展开, 我们得到:

\[\hat{F}(x)=e^x=\sum_{n\ge 0}\frac{x^n}{n!}\leftrightarrow \{1,1,1,...\} \]

待我之后学完多项式exp再继续补充

本人学习的时候, 主要参考了:
OI.wiki
算法|小学生都能看懂的生成函数入门教程- 牛客竞赛

posted on 2025-07-23 19:34  dddsx259  阅读(28)  评论(0)    收藏  举报