定义与严格化
对于一个数列{an},我们可以定义一个关于z的函数F(z)=n≥0∑anzn。这个函数就称为这个数列对应的生成函数。
生成函数实际上并不是数学分析意义中的多项式函数,这里的z并不是某个实数或复数,而是一个形式上的数,所对应的级数也只是一个形式级数。这些代数运算本质上是定义在(⋯,a−1,a0,a1,⋯)这个无穷维向量上的运算法则。在z的收敛半径内,形式级数有着和多项式类似的运算法则。所以,我们不必太关心为什么我们可以对生成函数进行这些运算,我们只需要知道这么做是正确的。对形式级数严格化的证明,除了能向我们证实这确实是对的以外没有别的意义,而这个工作前人已经帮我们做好了。
封闭表达式
一些数列的生成函数往往具有简洁的封闭表达式:
如果an=1,那么对应的有F(z)=n=0∑∞zn=1−z1。在这里,我们用到了等比级数的求和运算,这个运算在形式级数上是正确的。右侧的封闭表达式和左侧的无穷级数表达的含义是完全相同的。
如果ak=(kn),那么F(z)=k=0∑n(kn)zk=(1+z)n。这里用到了二项式定理。
如果ak=((nk))=(kn+k−1),我们记得它的组合意义是k个一样的小球放进n个不同的箱子里,箱子可以为空。这等价于插隔板,因此等价于找n个和为k的数的个数(考虑顺序)。这可以理解为生成函数中z的指数运算。如果写出F(z)=(1+z+z2+⋯)n,那么展开以后zk的系数恰好对应了方案数。因此F(z)就是我们要的生成函数。而每个括号内我们都能够写成封闭表达式1−z1,因此F(z)=(1−z)n1。
基本运算
对于两个生成函数F(z)=n∑fnzn,G(z)=n∑gnzn。那么有运算法则:
[zk](F+G)=fk+gk
[zk](zmF)=fk−m
[zk](c⋅F)=cfk
[zk](F′)=(k+1)fk+1
斐波那契通项公式(二阶线性递推)
我们把斐波那契数列拓展到下标为全体整数,定义n≤0时fn=0,n>0时fn=fn−1+fn−2+1[n=1]。两边同时乘以zn得fnzn=fn−1zn+fn−2zn+1[n=1]zn。这个等式对全体整数n成立,对全体等数累加得n∑fnzn=zn∑fn−1zn−1+z2n∑fn−2zn−2+z。将生成函数的定义代入得F(z)=zF(z)+z2F(z)+z。由此解得封闭表达式F(z)=1−z−z2z。裂项得F(z)=51⋅1−21+5z1−51⋅1−21−5z1。即F是两个生成函数的和,这两个生成函数都是等比级数。因此可以写出[zn]F(z)=[zn](51⋅1−21+5z1)−[zn](51⋅1−21−5z1),即fn=51(21+5)n−51(21−5)n。
扇形图的生成树(n阶线性递推)
有0到n共n+1个节点,1到n依次相连形成一条链。并且1到n的每个点都与0相连,形成一张扇形图,求这张图的生成树个数fn。
假设(0,n)这条边没被选,那么必须选择(n,n−1)这条边。而余下的0到n−1这个子图必须选出一颗生成树,而fn−1中的每个方案都是可行的。因此方案数为fn−1。
假设(0,n)这条边被选了,我们枚举链上的选边情况。考虑链上从n到k间的每条边都被选,而k到k−1的边没有被选(2≤k≤n)。显然n到k这些点到0的边一定不能再选了。而1到k−1这些点必须构成生成树。和上面类似,每种情况的方案数都恰好为fk−1。还要考虑到k=1的情况贡献1。因此总方案数为k=2∑nfk−1+1。
所以可以写出递推式:fn=fn−1+k=1∑n−1fk+1[n>0]。当n≤0时,fn=0。
那么考虑用生成函数,得到n∑fnzn=zn∑fn−1zn−1+n∑(k=1∑n−1fk)zn+n≥1∑zn。其中n∑(k=1∑n−1fk)zn=k≥1∑fk(n≥k+1∑zn)=k≥1∑fkzk(n≥k+1∑zn−k),右侧即为k≥1∑fkzk⋅1−zz。将生成函数代入,F(z)=zF(z)+F(z)1−zz+1−zz,解得F(z)=1−3z+z2z。同样裂项就可以求出fn的通项是等比加等比的结构。
卷积(生成函数的乘法)
把两个生成函数F(z)=n∑fnzn,G(z)=n∑gnzn相乘,那么根据多项式的运算法则,得到[zn]F(z)∗G(z)=k∑fkgn−k。
因此,如果生成函数的封闭表达式可以看作两个表达式的积,那么它的通项就可以用f,g的通项的卷积表示。比如,k个相同的小球放进n个不同的箱子,每个箱子小球个数不能超过t个。那我们用生成函数容易写出fn=[zk](1+z2+⋯+zt)n=[zk](1−z1−zt+1)n,这可以看作(1−z)n1与(1−zt+1)n的乘积。而这两个生成函数对应数列的通项都是容易写出的。
卷积可以推广到多元的情形:[zn]F(1)(z)∗⋯∗F(m)(z)=i1+⋯+im=n∑j=1∏mfij(j)
通过多元卷积,我们对扇形图的生成树个数又有一种新的计算方法:考虑1到n的链在选边后被分成了m段,那么每段必须恰好只有一个点与0相连。因此可以直接写出fn=m>0∑i1+⋯+im=n∑j=1∏mij。考虑gn=n,有生成函数G(z)=n>0∑nzn=zn>0∑nzn−1=z(z+z2+⋯)′=z(1−zz)′=(1−z)2z。
于是fn=m>0∑[zn]Gm(z)=[zn]m>0∑Gm(z)。G(z)作为一个变量本身构成了等比数列,因此有fn=[zn]1−G(z)G(z)=[zn]1−3z+z2z。这和上面得到的结果是相同的。
数的分划
一个整数可以写成若干奇数的和,称为奇分划;一个整数也可惜写成若干互不相同的数的和,称为不同数分划。 欧拉用生成函数证明了:对于任意整数,奇分划的个数与不同数分划的个数是相同的。
奇分划可以写成生成函数的形式O(z)=(1+z2+⋯)(1+(z3)2+⋯)(1+(z5)2+⋯)⋯,它的封闭表达式为O(z)=1−z1⋅1−z31⋅1−z51⋯
而不同数分划的生成函数为D(z)=(1+z)(1+z2)(1+z3)⋯。应用平方差公式,D(z)=1−z1−z2⋅1−z21−z4⋅1−z31−z6⋯。分子上的偶数项都会被约分,从而恰好得到O(z)=D(z)。
第二类斯特林数的生成函数
斯特林数是一个二元函数。我们考虑固定k的斯特林数形成的生成函数:Sk(z)=n∑{nk}⋅zn。考虑到边界情况后,有递推关系:
{nk}={n−1k−1}+k{n−1k}+1[n=k=0]
那么依照生成函数求解递推式的惯例,两边同时乘以zn并对全体整数n累加得到Sk(z)=zSk−1(z)+kzSk(z),即Sk(z)=1−kzzSk−1(z)。累乘(其中S0(z)=1)得到Sk(z)=j=1∏k(1−jz)zk。
对Sk(z)裂项,假设Sk(z)=j=1∑k1−jzαj+C。此时我们可以用有理函数积分时待定系数的trick,在求解αi时在等式两边同时乘以1−iz,此时等式关系依然对z恒成立。那么取z=i1,则左边变成j=i∏(1−j/i)(1/i)k,而右边只剩下αi。因此αi=j=i∏(1−j/i)1/ik= ij=i∏(i−j)1=i!(k−i)!(−1)k−i=(−1)k−i(ik)⋅k!1。
因此[zn]Sk(z)=j=1∑kαj⋅jn=j=1∑k(−1)k−j(jk)k!jn=k!1i=0∑k−1(−1)i(ik)(k−i)n
=k!1i=0∑k(−1)i(ik)(k−i)n。可以发现和我们用容斥得到的结论是一致的。
卡特兰数
n个节点的二叉树形态数量cn称为卡特兰数列。容易发现有递推式
cn=k=0∑n−1ck⋅cn−1−k+1[n=0]
设生成函数C(z)=n∑cnzn两边同时乘以zn并对全体整数n求和(中间的部分是卷积),得到C(z)=z[C(z)]2+1。二次方程求根公式得C(z)=2z1±1−4z。由于C(0)=1,所以舍去2z1+1−4z(发散),并且确实有z→0lim2z1−1−4z=z→0lim2z(1+1−4z)1−(1−4z)=1。因此C(z)=2z1−1−4z。由广义二项式定理展开得1−4z=n≥0∑(n21)(−4z)n。代入得C(z)=2z1−n≥0∑(n21)(−4z)n=2z−n≥1∑(n21)(−4z)n=2n≥1∑(n21)(−4z)n−1 =2n≥0∑(n+121)(−4)nzn。
因此cn=2(n+11/2)(−4)n=2(n+1)!(21−0)(21−1)⋯(21−n)(−2)n2n =(n+1)!(−1+2)(−1+4)⋯(−1+2n)2n=(n+1)!(2n−1)!!2n=(2n)!!(n+1)!(2n)!2n =n!⋅2n⋅(n+1)!(2n)!2n=n+11(n2n)
指数生成函数
考虑一个最简单的递推关系fn=nfn−1+1[n=0]。显然fn=n!。但当我们试图用普通的生成函数去根据递推关系求解通项时却碰到了问题:设F(z)=n∑fnzn。在递推关系两边同时乘以zn并对n求和,得到n∑fnzn=n∑fn−1⋅nzn+1。由于F′(z)=n∑fn⋅nzn−1,因此n∑fn−1nzn=n∑fn−1(n−1)zn+n∑fn−1zn= n∑fn⋅nzn+1+zF(z) =z2F′(z)+zF(z)。原式即为F(z)=z2F′(z)+zF(z)+1。这是一个微分方程,并且恰好没有封闭形式的解。
为了处理这类问题,我们使用“指数生成函数”。数列fn的指数生成函数定义为F(z)=n≥0∑n!fn⋅zn。我们注意到当fn≡1时,F(z)=n≥0∑n!zn,根据Taylor公式有F(z)=ez。
因此,当我们已知fnzn=fn−1⋅nzn+1[n=0]时,两边同时除以n!再对n累加,得到n∑n!fnzn=n∑(n−1)!fn−1zn+1,所以F(z)=zF(z)+1,解得F(z)=1−z1。因此[zn]F(z)=1=n!fn,解得fn=n!。
指数生成函数的卷积和二项式有相似之处:设F(z)=n≥0∑n!fn⋅zn,G(z)=n≥0∑n!gn⋅zn。设H(z)=n≥0∑n!hnzn,那么[zn](F∗G)=k=0∑nk!(n−k!)fkgn−k=n!hn。因此hn=k=0∑nk!(n−k!)n!fkgn−k=k=0∑n(kn)fkgn−k
生成树计数
我们认为n个有编号的节点的两个生成树是相同的当且仅当每个对应节点的父节点编号与子节点编号全都相同。设n个节点的可能生成树个数是tn个。考虑递推关系,把其中一个节点固定为根节点,我们枚举其子树个数m。每一次需要各个子树中的节点个数ki满足k1+⋯+km=n−1,对于每种{ki}的选取,方案数为(k1n−1)(k2n−1−k1)⋯(kmkm)=k1!(n−1−k1)!(n−1)!⋅k2!(n−1−k1−k2)!(n−1−k1)!⋯1 =k1!⋯km!(n−1)!。在考虑子树顺序的前提下,我们的统计是完全的并且不重复的。而子树的顺序是不能认为是不同的生成树个数的。答案中的一种分组方案在我们的统计方法中会被重复统计m!遍。每个分组中生成树的方案数是tki,并且我们可以任意选一个点作为子树的根节点。综上,有递推关系:
tn=m=1∑n−1m!1∑ki=n−1∑k1!⋯km!(n−1)!tk1⋯tkm⋅k1⋯km
有tn=m=1∑n−1m!1∑ki=n−1∑(n−1)!(k1−1)!tk1(k2−1)!tk2⋯(km−1)!tkm
我们发现(i−1)!ti是一个共同的结构,因此有(n−1)!tn=m=1∑n−1m!1∑ki=n−1∑j=1∏m(kj−1)!tkj
我们将发现,这个问题用指数生成函数求解起来是方便的。设n!un=(n−1)!tn,即un=ntn,那么n!un=m=1∑n−1m!1∑ki=n−1∑j=1∏mkj!tkj。设U(z)=n∑n!unzn,右侧是U的m元卷积的形式。因此两边同时乘以zn对所有n累加,有
[zn]U(z)=[zn]m=1∑n−1m!z[U(z)]m=[zn−1]m≥1∑m![U(z)]m
生成函数本身构成了自然对数幂级数的形式,因此
=[zn−1](eU(z)−1)=[zn]zeU(z)
因此得到方程U=zeU。由拉格朗日反演定理得[zn]U(z)=(n−1)!nn−2=n!un。因此tn=nun=nn−2。