学习笔记——生成函数初见

可能不严谨,但是能看懂,并且可以用~

概论#

你从小就被 myee 在生物课上教育生成函数,但是那个时候的你,连生成函数是什么都不知道。

后来,你在学考前粗粗地看了看,发现完全没法看懂。

最后,听 Mr_Spade 讲生成函数,终于初步弄懂了生成函数,并经过一些例题的磨炼稍微能推一下式子,于是就来这里写博客了。

首先我们需要一些前置芝士——多项式及其基本运算。

前置芝士#

主要介绍多项式和基本的运算,如果你已经熟练掌握,可跳过此部分。

多项式表示#

这个大家都会,用一个 f 来表示一个多项式,而 [xn]f 表示多项式 f 的第 n 次项的系数。

多项式乘法#

你可以考虑一波小学的时候学的分配律,然后合并同类项,就是我们所说的多项式乘法。基于此,我们有一个 O(n2) 的乘法:

[xn]h=k=0n[xk]f[xnk]g

我们把这个玩意儿记作:

h=fg

然后如果你会 FFT 或者 NTT 等算法,可以把它优化到 O(nlogn)

顺带一提(下面要用),若干多项式相乘会有如下形式:

[xn](f1fm)=k1,,km[j=1mki=n](j=1m[xkj]fj)

多项式求逆#

有的时候,我们会在模意义下,求两个多项式的乘法,如果多项式 f,g 满足:

fg1(modp)

那么 f,g 就是互逆的,我们类比于整数的逆元,记作:

g=f1

那么我们根据乘法的定义,可以推出求逆的式子:

[xn]f1={1[x0]f,n=0k=0n1[xk]f1[xnk]f[x0]f,n>0

多项式复合#

也就是喜闻乐见的函数嵌套,我们记作 fg。一般不会直接计算。

多项式求导#

这东西大家都会,有:

[xn]f=(n+1)[xn+1]f

然后一些性质:

(f±g)=f±g

(fg)=fg+fg

(fg)=fgg

根据这些性质,我们可以得到:

(fg)=fgfgg2

多项式 exp#

也称为多项式指数函数。记作:ex

其来源于我们希望能得到一个多项式使得其导数是其本身。根据求导的定义,我们有:

[xn]f=(n+1)[xn+1]f=[xn]f

[xn+1]f=[xn]fn+1

此时我们令 [x0]f=1,则有:

ex=k0xkk!

那么我们定义一个多项式 f 的指数函数为其和 ex 的复合,记作:ef。则易得:

ef=k0fkk!

根据上式,我们注意到 fk 的前 k 项是 0,所以如果我们需要求指数函数的第 n 项系数,可以这样子:

[xn]ef=k=0n[xn]fkk!

顺带一提,指数函数有着代数相似的良好性质:

ef+g=efeg

ekf=(ef)k

为了更快地求指数函数,我们利用导数:令 g=ef,则有:

g=(exf)=(ex)ff=exff=eff=gf

于是我们分别取第 n 项系数:

(n+1)[xn+1]g=k=0n[xk]g[xnk]f

有了这个式子可以 O(n2) 递推,当然也可以优化到 O(nlogn)

多项式 ln#

你可以把这玩意儿看成是代数的对数。即有:

ef=glng=f

快乐。

至此,多项式的基本运算,也就是生成函数的基础就介绍完毕。

进入正题#

普通生成函数#

首先,我们需要明确一件事:生成函数是什么。这里抽象地解释一下就是:对于一个数列 a多项式 f 如果满足:

an=[xn]f

则我们称这个多项式 f 是数列 a 的一个普通生成函数(OGF)。是的,生成函数是一个一个一个多项式!

引入#

考虑一个小学生题。

你有 a 件不同的上衣,b 条不同的裤子,c 双不同的鞋子。问你有多少种不同的搭配方式?

你是这样算的:上衣有 a 种选择,裤子是 b 种,鞋子是 c 种,那么根据乘法原理应当是 a×b×c 种。

然而,如果我们把每种选择用加法原理展开,应该是这样的:

(1+1++1)×(1+1++1)×(1+1++1)a1b1c1

以上只是感受一下。

然后我们继续问:

如果这 a 件上衣,b 条裤子和 c 双鞋子分别都有特定的价格,那请问,总价格是 n 的方案数是多少?

这个题好像可以 dp?我们可以考虑设 dp1/2/3,i 表示考虑了衣服/衣服+裤子/衣服+裤子+鞋子之后总价是 i 的方案数。然后暴力转移就是 O(nm) 的了,其中 m 就是 a+b+c。这个东西已经很难优化了。

但是我们来一波人类智慧,我们利用生成函数,使得其能通过某种代数运算的方式直接完成一整行的转移。我们掏出三个多项式 A,B,C,分别表示衣服裤子和鞋子。然后 [xn]A 表示衣服中价格为 n 的数量,以此类推。

然后我们把这三个多项式乘起来,得到 f,那么有:

[xn]f=a,b,c[a+b+c=n][xa]A[xb]B[xc]C

现在,我们把这个多项式的 x 的指数看成是上面 dp 中的 i,那么我们惊奇地发现,这个东西实际上就是 dp 的转移。然后我们考虑 f 是啥。我们假设数列 b,其中 bi 表示 n=i 时的答案。不难发现,f 就是答案数列 b 的生成函数。

也就是说,我们将这三个多项式乘起来,然后取第 n 项系数,就是我们需要求的答案。这个东西,用 FFT/NTT 可以优化到 O(nlogn)

经过上面这个例子,我们不难发现,生成函数实际上是借助于 x 的指数来区分不同的系数,可以把它当成 dp 的下标(或者说是状态)。因此,我们不会向生成函数中带入任何 x 的值,它只作为一个标志。

求 OGF#

有了对生成函数的初步了解,来看几道题吧。

有无穷多张 1,5,10,20,50,100 元的纸币,求凑成 n 元的方案数。

我们来求它的生成函数。考虑每种纸币选多少,那么对于面值是 i 的纸币,其构成多项式:

fi=k0xki=11xi

那么我们将这些多项式全部乘起来,和第一个例子相同,相当于让他们自由组合。最后这个多项式就是答案序列的生成函数,那我们取第 n 项系数,就是答案了。

设斐波那契数列生成函数 f,且 [x0]f=0,[x1]f=1,求 f

不同与之前所遇到的组合题,这题直接要求一个特定数列的生成函数。面对这种问题,通常选择先写出递推式子:[xn]f=[xn1]f+[xn2]fn2。然后我们把他全部转化成同一项的系数,即:[xn]f=[xn]fx+[xn]fx2,通过移项化简得到:

[xn](f(1xx2))=0

也就是说多项式 f 乘上多项式 1xx2 后第 n 项(n2)的系数永远是 0

然后我们考虑 n=1 的情况,那么有:

[x1](f(1xx2))=[x1]f1+[x0]f(1)=1

以及 n=0 的情况,那么有:

[x0](f(1xx2))=[x0]f1=0

那么也就是说,对于多项式 g=f(1xx2),只有一次项系数为 1,其余都是 0,那么就容易得到 g=x,那么就有:

f=x1xx2

这便是斐波那契数列的生成函数。

指数生成函数#

我先不说这是个啥,我们先来引入。

引入#

先来考虑这样一个问题:

给你一张完全图,求生成树的个数。

这个问题直接用矩阵树定理,求行列式之后可以得到应该是 nn2

现在我们把这个题升级一下:

n 个点的无向图,形状恰好是不连通的两棵树的图的数量。

看到这个题可以想到是相当于求两棵不相交的生成树。那么想要把图分成两部分。于是你写出了这样一个暴力求的式子:

k0n(nk)×12×kk2×(nk)nk2

这个 12 是因为我们需要去除两棵树的顺序。

类似于上面提到的 OGF,我们尝试把这玩意儿变成答案数列的生成函数的系数,即:

[xn]f=12k0nn!k!(nk)!×kk2×(nk)nk2

我们巧妙地分配这个组合数的阶乘,得到:

[xn]fn!=12k0nkk2k!×(nk)nk2(nk)!

然后我们非常智慧地定义一个 g 是第一个问题的生成函数,那么有:

[xn]g=nn2

欸那我们带入上面这个式子不就是:

[xn]fn!=12k0n[xk]gk!×[xnk]g(nk)!

然后我们有一个 [xn]F=[xn]fn!,[xn]G=[xn]gn!。带入得到:

F=G22

很神奇,如果我们知道了 G(而我们确实容易计算这个多项式),那么通过多项式乘法就能得到 F 了。复杂度可以是 O(nlogn)

我们发现上面这个 F,G 两个多项式和 OGF 不同,它在 OGF 的基础上除了一个阶乘,很像多项式指数函数的形式,所以我们叫它指数生成函数(EGF)

有了 EGF,我们可以继续升级上面这个问题:

EGF 的进一步应用#

现在来考虑这样一个问题:

n 个点的无向图中,形状恰好是不连通的若干棵树的图的数量。

换句话说,我们把前面的 2 变成了若干。

同样我们先写出这个暴力的式子:

[xn]f=k0n1k!a1,,ak[i=0kai=n](na1,,ak)(i=1k[xai]g)

模仿上面分配这个组合数,得到:

F=Gkk!

你是否觉得眼熟,啊对,这东西就是指数函数:

F=eG

好家伙。。。

总结#

我们现在遇到了两种生成函数,也是最常见的两种。这两种生成函数都会用于组合计数类问题中。OGF 擅长对于组合成为特定值的问题,而 EGF 擅长对于树图的计数,其特点是暴力计算式子中含有二项式,然后通过巧妙分配其阶乘可以得到 EGF。

posted @   ZCETHAN  阅读(73)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示
主题色彩