学习笔记——生成函数初见
可能不严谨,但是能看懂,并且可以用~
概论#
你从小就被 在生物课上教育生成函数,但是那个时候的你,连生成函数是什么都不知道。
后来,你在学考前粗粗地看了看,发现完全没法看懂。
最后,听 讲生成函数,终于初步弄懂了生成函数,并经过一些例题的磨炼稍微能推一下式子,于是就来这里写博客了。
首先我们需要一些前置芝士——多项式及其基本运算。
前置芝士#
主要介绍多项式和基本的运算,如果你已经熟练掌握,可跳过此部分。
多项式表示#
这个大家都会,用一个 来表示一个多项式,而 表示多项式 的第 次项的系数。
多项式乘法#
你可以考虑一波小学的时候学的分配律,然后合并同类项,就是我们所说的多项式乘法。基于此,我们有一个 的乘法:
我们把这个玩意儿记作:
然后如果你会 FFT 或者 NTT 等算法,可以把它优化到 。
顺带一提(下面要用),若干多项式相乘会有如下形式:
多项式求逆#
有的时候,我们会在模意义下,求两个多项式的乘法,如果多项式 满足:
那么 就是互逆的,我们类比于整数的逆元,记作:
那么我们根据乘法的定义,可以推出求逆的式子:
多项式复合#
也就是喜闻乐见的函数嵌套,我们记作 。一般不会直接计算。
多项式求导#
这东西大家都会,有:
然后一些性质:
根据这些性质,我们可以得到:
多项式 exp#
也称为多项式指数函数。记作:。
其来源于我们希望能得到一个多项式使得其导数是其本身。根据求导的定义,我们有:
此时我们令 ,则有:
那么我们定义一个多项式 的指数函数为其和 的复合,记作:。则易得:
根据上式,我们注意到 的前 项是 ,所以如果我们需要求指数函数的第 项系数,可以这样子:
顺带一提,指数函数有着代数相似的良好性质:
为了更快地求指数函数,我们利用导数:令 ,则有:
于是我们分别取第 项系数:
有了这个式子可以 递推,当然也可以优化到 。
多项式 ln#
你可以把这玩意儿看成是代数的对数。即有:
快乐。
至此,多项式的基本运算,也就是生成函数的基础就介绍完毕。
进入正题#
普通生成函数#
首先,我们需要明确一件事:生成函数是什么。这里抽象地解释一下就是:对于一个数列 ,多项式 如果满足:
则我们称这个多项式 是数列 的一个普通生成函数(OGF)。是的,生成函数是一个一个一个多项式!
引入#
考虑一个小学生题。
你有 件不同的上衣, 条不同的裤子, 双不同的鞋子。问你有多少种不同的搭配方式?
你是这样算的:上衣有 种选择,裤子是 种,鞋子是 种,那么根据乘法原理应当是 种。
然而,如果我们把每种选择用加法原理展开,应该是这样的:
以上只是感受一下。
然后我们继续问:
如果这 件上衣, 条裤子和 双鞋子分别都有特定的价格,那请问,总价格是 的方案数是多少?
这个题好像可以 dp?我们可以考虑设 表示考虑了衣服/衣服+裤子/衣服+裤子+鞋子之后总价是 的方案数。然后暴力转移就是 的了,其中 就是 。这个东西已经很难优化了。
但是我们来一波人类智慧,我们利用生成函数,使得其能通过某种代数运算的方式直接完成一整行的转移。我们掏出三个多项式 ,分别表示衣服裤子和鞋子。然后 表示衣服中价格为 的数量,以此类推。
然后我们把这三个多项式乘起来,得到 ,那么有:
现在,我们把这个多项式的 的指数看成是上面 中的 ,那么我们惊奇地发现,这个东西实际上就是 的转移。然后我们考虑 是啥。我们假设数列 ,其中 表示 时的答案。不难发现, 就是答案数列 的生成函数。
也就是说,我们将这三个多项式乘起来,然后取第 项系数,就是我们需要求的答案。这个东西,用 FFT/NTT 可以优化到 。
经过上面这个例子,我们不难发现,生成函数实际上是借助于 的指数来区分不同的系数,可以把它当成 的下标(或者说是状态)。因此,我们不会向生成函数中带入任何 的值,它只作为一个标志。
求 OGF#
有了对生成函数的初步了解,来看几道题吧。
有无穷多张 元的纸币,求凑成 元的方案数。
我们来求它的生成函数。考虑每种纸币选多少,那么对于面值是 的纸币,其构成多项式:
那么我们将这些多项式全部乘起来,和第一个例子相同,相当于让他们自由组合。最后这个多项式就是答案序列的生成函数,那我们取第 项系数,就是答案了。
设斐波那契数列生成函数 ,且 ,求 。
不同与之前所遇到的组合题,这题直接要求一个特定数列的生成函数。面对这种问题,通常选择先写出递推式子:,。然后我们把他全部转化成同一项的系数,即:,通过移项化简得到:
也就是说多项式 乘上多项式 后第 项()的系数永远是 。
然后我们考虑 的情况,那么有:
以及 的情况,那么有:
那么也就是说,对于多项式 ,只有一次项系数为 ,其余都是 ,那么就容易得到 ,那么就有:
这便是斐波那契数列的生成函数。
指数生成函数#
我先不说这是个啥,我们先来引入。
引入#
先来考虑这样一个问题:
给你一张完全图,求生成树的个数。
这个问题直接用矩阵树定理,求行列式之后可以得到应该是 。
现在我们把这个题升级一下:
求 个点的无向图,形状恰好是不连通的两棵树的图的数量。
看到这个题可以想到是相当于求两棵不相交的生成树。那么想要把图分成两部分。于是你写出了这样一个暴力求的式子:
这个 是因为我们需要去除两棵树的顺序。
类似于上面提到的 OGF,我们尝试把这玩意儿变成答案数列的生成函数的系数,即:
我们巧妙地分配这个组合数的阶乘,得到:
然后我们非常智慧地定义一个 是第一个问题的生成函数,那么有:
欸那我们带入上面这个式子不就是:
然后我们有一个 。带入得到:
很神奇,如果我们知道了 (而我们确实容易计算这个多项式),那么通过多项式乘法就能得到 了。复杂度可以是 。
我们发现上面这个 两个多项式和 OGF 不同,它在 OGF 的基础上除了一个阶乘,很像多项式指数函数的形式,所以我们叫它指数生成函数(EGF)。
有了 EGF,我们可以继续升级上面这个问题:
EGF 的进一步应用#
现在来考虑这样一个问题:
求 个点的无向图中,形状恰好是不连通的若干棵树的图的数量。
换句话说,我们把前面的 变成了若干。
同样我们先写出这个暴力的式子:
模仿上面分配这个组合数,得到:
你是否觉得眼熟,啊对,这东西就是指数函数:
好家伙。。。
总结#
我们现在遇到了两种生成函数,也是最常见的两种。这两种生成函数都会用于组合计数类问题中。OGF 擅长对于组合成为特定值的问题,而 EGF 擅长对于树图的计数,其特点是暴力计算式子中含有二项式,然后通过巧妙分配其阶乘可以得到 EGF。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人