OGF 学习笔记

生成函数(generating function,简称 GF),一般只应用两种:OGF 和 EGF。

OGF 和 EGF 都是定义在一个数列上的。

【一些前置知识】

二项式卷积:cn=i=0(in)aibni

exp(A(x))=i0A(x)ii!

ln(1A(x))=i1A(x)ii

exp(ln(f(x)))=f(x)

复合函数求导:f(g(x)) 的导 =f(g(x))g(x)

指数函数的导:(ax)=axlna

幂函数的导:(xa)=axa1

对数函数的导:(logax)=1xlna。特别地,(lnx)=1x

【OGF】

【定义】

对于一个有限序列 {ai}(i=0N),其 OGF 为 f(x)=i=0Naixi

对于一个无限序列 {ai},其 OGF 为 f(x)=i=0+aixi

注意生成函数是一种形式幂级数,也就是一般情况下我们不考虑 x 具体的值,也不考虑 f(x) 是否收敛。

(我们把 i=0+aixi 的形式称为级数)

:有时也把 OGF 称作母函数。

砝码称重

4 砝码,分别为 1,2,3,4 克。问称出 n 克的方案数。(砝码只能放在一边)

G(x)=(1+x1)(1+x2)(1+x3)(1+x4),发现 ans=[xn]G(x)。(在一个多项式前加中括号,表示取中括号内的项的系数)

怎么理解呢?G(x) 每一个括号都代表一个砝码的选择:放或不放。

取球方案

m 种颜色的球,要从里面取出 n 个球。问方案数。同时有两种情况:

  • 每种颜色的球各一个。显然答案是 (nm)

  • 每种颜色的球无限个。即求方程 x1+x2++xm=n 非负整数解个数,隔板法 (m1n+m1)

怎么用生成函数做?

当每种球只有一个,令 G(x)=(1+x)mans=[xn]G(x)。显然可以验证,与上面相等。

当每种球有无限个,令 G(x)=(1+x+x2+x3+)m=(11x)m=1(1x)m=(1x)m

这里用到广义二项式定理

可得 (1x)m=i=0+(im)(x)i,则 xn 的系数就是 (1)n(nm)=(1)n(m)(m1)(mn+1)n!

把前面的 n1 挪到分子上面,m(m+1)(m+2)(m+n1)n!=(nm+n1),也与上面相等。

装水果

类似这题

要求苹果个数为偶数,香蕉个数为 5 的倍数,橙子个数为 04,梨个数是 01。求拿 n 个的方案数。

考虑生成函数 G(x)=(1+x2+x4+)(1+x5+x10+)(1+x++x4)(1+x)ans=[xn]G(x)

G(x)=11x211x51x51x(1+x)=1(1x)2=(1+x+x2+)(1+x+x2+)

观察可得 [xn]G(x)=n+1

【运算规则】

记数列 {f} 的生成函数是 F(x)

  • 扩倍规则:若 {f} 每一项乘以 C,则 F(x)CF(x)

  • 加法规则:若有另一个数列 {g} 的生成函数是 G(x),则 {f+g} 的生成函数是 F(x)+G(x)

  • 右移规则:若让 {f} 开头加上 k0,则 F(x)xkF(x)

  • 求导规则<f0,f1,>F(x),则 <f1,2f2,3f3,>F(x),这里就是从 f1 开始,不是打错了。

练习:求 <02,12,22,> 的 OGF。

<1,1,1,1,>11x,则 <1,2,3,>1(1x)2

注意这里的求导:(11x) 属于复合函数求导。

又有 <0,1,2,>x(1x)2。再用一次求导。<12,22,>(1+x)x(1x)3

注意这里的求导:x(1x)2 是除法求导,(A(x)B(x))=A(x)B(x)A(x)B(x)B2(x)

  • 乘法法则:若有两个数列 a,b 和生成函数 A(x),B(x),则生成函数为 A(x)B(x) 的数列为 a,b 的卷积。(EGF 对应的是二项式卷积)

【OGF 求递推公式】

汉诺塔问题

fn=2fn11,f0=0,求 fn

用归纳法很容易,但是怎么用生成函数做?

考虑 f 的生成函数 F(x)=f0+f1x+f2x2+

f0=0f1x=(2f0+1)xf2x2=(2f1+1)x2,……,fnxn=(2fn1+1)xn

每个等号左右两边各自加起来,有 F(x)=2xF(x)+x(1+x+x2+)

所以 (12x)F(x)=x1xF(x)=x(1x)(12x)=112x11x=(1+2x+(2x)2+)(1+x+x2+)

观察可以发现 [xn]F(x)=2n1

斐波那契数列

fn=fn1+fn2,f0=0,f1=1,求 fn

矩阵快速幂当然可以。但是我们这里还是考虑生成函数 F(x)

同样把每个等号左右两边加起来,F(x)=xF(x)+x2F(x)+x,则 F(x)=x1xx2

这里可以因式分解1xx2=(11+52x)(1152x)。刚好可以裂项。令 a=1+52,b=152

可得 F(x)=151ax151bx=n=0+15anxn15bnxn

所以 fn=anbn5

卡特兰数

f0=1,fn=f0fn1++fn1f0

(众所周知,fn=C2nnn+1

同样等号两边相加,F(x)=1+f0xF(x)+f1x2F(x)+f0x3F(x),F(x)1=F(x)(f0x+f1x2+)=xF(x)2

xF(x)2F(x)+1=0,F(x)=1+±14x2x,那这里是取加号还是减号呢?应该取减号。

为什么不取加号?因为 F(x)=1+14x2xx=0 时为 1+10=+。而取减号时,F(x)x=0 时为 00,可以用洛必达法则验证其趋向于 1

于是 F(x)=114x2x=12x12x(14x)12,用广义二项式定理展开。

F(x)=12x12xi=0+(i12)(4x)i

观察得 fn=[xn]F(x)=12(n+112)(4)n+1,还能进一步简化到 (n2n)n+1


对于一个 k 次齐次线性递推式:fn+c1fn1++ckfnk=0f0=d0,f1=d1,,fk1=dk1

只要是这种形式,生成函数 F(x) 可以表示为 P(x)R(x)P(x) 是一个根据 c,d 推出来的多项式,R(x)=1+c1x++ckxk。(R(x)f 的特征多项式)

【OGF 的具体应用和 tricks】

例1:整数的 lqp 拆分

题意:定义 n 的一个 lqp 拆分是把 n 拆成若干个有序的正整数之和。同时记 f 为斐波那契数列。
定义一个 lqp 拆分的权值为:它拆出来的所有数为 a1am,权值为 fa1fa2fam,求 n 的所有 lqp 拆分的权值和。n10100000

gnn 的答案。则当 n>0gn=fn+i=1n1figni

为了方便,令 g0=1,这样 fn 可以表示为 fng0

如此,gn=i=1nfigni(n>0)

还是考虑生成函数 G(x)。还是用上面的方法。

g0=1,g1x=(f1g0)x,g2x2=(f2g0+f1g1+f0g2)x2,

但是直接加没有结果,把 g0 改写为 1+f0g0,这样可以得出 G(x)=F(x)G(x)+1,其中 F(x) 是斐波那契数列的生成函数。(利用乘法法则!)

所以 1=G(x)(1F(x))G(x)=11F(x),又 F(x)=x1xx2(上面算过了)。

G(x)=11x1xx2=1xx212xx2

怎么求 [xn]G(x)

(12xx2)G(x)=1xx2,我们尝试比较左右两边 xn 的系数。(假设 n>2

右边系数为 0,左边系数为 gn2gn1gn2,所以 gn=2gn1+gn2,初值 g0,g1 显然可以算。于是用矩阵快速幂就可以了。

从母函数推原递推式:比较系数法

例2

随机生成 n 个结点的有根二叉树。问叶子个数的期望值。

cnn 个结点有根二叉树的个数,hnn 个结点有根二叉树的叶子总数。答案为 hncn

cn 怎么算?枚举左右两个子树的点个数,cn=cicn1i,这就是卡特兰数。

h0=0h1=1,对于 n2hn=2i=0n1hicn1i

为什么?考虑一颗二叉树的叶子个数,我们可以先计算左边的点数以及左边子树的叶子数量:hi,对于每一个左边子树的 hi,右边子树都有 cn1i 种可能。所以左边子树贡献的叶子个数为 hicn1i

右子树也是对称的,所以要乘 2

那接下来怎么办呢?考虑 h,c 的母函数 H,C。因为 cn 是卡特兰数序列,所以 C(x)=114x2x

h0=h0h1x=h1xh2x2=2(h0c1+h1c0)x2h3x3=2(h2c0+h1c1+h0c2)x3

还是等号左右相加。H(x)h0h1x=H(x)x=2xH(x)C(x)

H(x)=2xH(x)C(x)+x

H(x)=x12xC(x)=x12x114x2x=x14x=x(14x)12

广义二项式定理展开,H(x)=xi=0+(i12)(4x)i

h(n)=[xn]H(x)=(n112)(4)n1,化简为 (n12n2),化简过程略,就是展开 (n112) 后和 (4)n112 抵消。

h(n)c(n)=(n12n2)(n2n)/(n+1).

拆分方案

题意:把 n 拆成若干 2,3,4 的和,不考虑顺序,求方案数。

G(x)=(1+x2+x4+)(1+x3+x6+)(1+x4+x8+)=11x211x311x4.

G(x)=g0+g1x+g2x2+,H(x)=1/G(x)=(1x2)(1x3)(1x4)。显然 H(x) 很容易展开。

H(x)=h0+h1x+h2x2++h9x9。这里 h0h9 都是可以求出来的。同时注意 h0=1。((1x2)(1x3)(1x4) 的常数项当然是 1

G(x)H(x)=1,因为倒数嘛。根据母函数的乘积 =1,可以推出两个数列的卷积的关系。

g0h0=1g0h1+g1h0=0g0h2+g1h1+g2h0=0gn9h9++gnh0=0(n9)

观察 gn9h9++gnh0=0,这是一个线性齐次递推式!而且因为 h0h9 都能求,所以 g0g8 也能求。

对于 n9,可以用矩阵快速幂搭配递推式,O(logn93) 的复杂度。

这里采用倒数的方法,原因是倒数的形式简单,而且线性齐次递推式的项数比较少。

CF506E子问题

题意:
p 个字符串 s1sp,由字符 ax 组成。
q 个字符串 t1tp,由字符 ay 组成。
1 个字符串 R,由 az 组成。
已知总长度和为 l,允许空串。求方案数。p,q200

G(x)=(1+24x+242x2+)p(1+25x+252x2+)q(1+26x+262x2+)1ans=[xl]G(x)

G(x)=(124x)p(125x)q(126x)。如果和上面一样采取倒数的 trick,可以做到 O(logL4013)

UOJ424

题意:左拐度 <mn 个结点二叉树计数。定义左拐度为所有根到叶子的路径中,向左走的次数的最大值。n,m105

fn,m 表示左 <m(注意是小于不是小于等于),结点数 =n 的二叉树个数。

{Fn,0=[n=0]Fn,1=1Fn,m=i=0n1Fi,m1Fn1i,m(枚举左右子树)

观察 Fn,m=i=0n1Fi,m1Fn1i,m 的形式,是一个卷积,所以考虑使用母函数。

Fm(x)<F1n,m> 的母函数.

类似地,可以推出 Fm(x)=xFm1(x)Fm(x)Fm(x)=11xFm1(x)

如果暴力从 F1(x) 算到 Fm(x),复杂度会爆。

显然 Fm(x) 能写成 Am(x)Bm(x) 的形式。而且可以发现,Am+1(x)=Bm(x)。因此我们只需要记录每一个 Bi(x) 即可,Ai(x) 可以用 Bi(x) 求出来。

Fm+1(x)=11xBm1(x)Bm(x)=Bm(x)Bm(x)xBm1(x)

Bm+1(x)=Bm(x)xBm1(x)。这又是一个递推式。

我们想用矩阵快速幂:因为这是一个线性齐次递推式。但是如果矩阵的元素是多项式,很麻烦;可以使用拉格朗日插值公式,随便选 mx 代入,得到 Bm(x)m 个值,进而推出 Bm(x) 的整个多项式。

Fm(x)=Bm1(x)Bm(x),同理求出 Bm1(x) 的整个多项式,用 O(nlogn) 的复杂度算出 Fm(x),然后 [xn]Fm(x) 就是 Fn,m 的值。

posted @   FLY_lai  阅读(90)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示