递推式(Recurrence)与生成函数(Generating Function)
前言
原文写于2014年3月22日。修订于2018年7月14日。
也是终于完成了这个系列第二篇,在寻找良好素材的时候也无意中发现了不少相关方面的优秀资料,一时兴起而做的决定为自己也带来了诸多益处,这实在令人欣慰.
用生成函数求解递推式是一个非常机械的过程,按照流程一步步做就能得到答案。不过大多数时候也并不像听上 去那么容易—如之前组合恒等式的证明那样,我们需要注意和处理令人厌烦的角标。
本文不期望读者能够掌握什么具体的知识,但如若能够为诸君于某刻解决问题时作一份参考,亦或是能有些许思路上的共鸣,之于我都将是莫大的荣誉。
0.符号约定
我们以
若
没有明确说明的情况下,
1.定义与基本性质
一般来说,给定一个序列
尽管定义中的
设
最后一个等式看起来非常的熟悉,在样式上似乎是我们在前一篇所提到过的卷积,应用前面曾提到的些许结论,我们令数列
这是一个非常有用的等式,他告诉我们用
注意到我们这里用了一些幂级数的基本知识(即
在这里我们不会用到什么深奥的幂级数知识,但即便如此,生成函数作为工具也已经十分强大。
简单的关于幂级数的知识可以让我们得到许多生成函数的封闭形式,例如调和数列
2.与递推式
我们希望借助幂级数来解决一些关于数列的问题,例如通过数列的递推式去求解通项公式,这也是我们引入生成函数的原因,那么它能够胜任么?
我们首先来看一个简单的例子。
ex.2.1 一个经典问题
假设我们有
个数 ,这 个数的乘积需要通过 次乘法来加以确定,因而我们要问,在乘积 中有多少种插入括号的方法 ,使得乘法的次序被完全指定(我们假定交换律并不成立)。
我们这样来思考这个问题,我们为这
由于递推式并没有
数列
这样我们很容易就能看出
经由一些简单的代数运算,我们就能得到
实际上求解上面的代数方程我们会得到关于
之后,只需要运用你在高数课上习得的知识,将
ex.2.2 源于快速排序
我们都知道快排的平均时间复杂度是
我们假设待排序数列为
选定枢纽元之后,设比枢纽元小的元素数量为
其中第一项的
令
求解这个微分方程,我们就能得到
来看看我们是怎么处理上面这个递推式的,在我们发现可能可以用到之前某些已经得到的结论的时候,
ex.2.3 它看起来奇怪而熟悉
或许更多时候我们遇到的递推式会是这样的
线性的递推项,和一个可能比较奇怪的尾项,运用我们之前所提到的技术,设
把边界加入进去,我们得到
再来看看右边的情况
且有
因而我们得到
这结果简直让人菊花一紧。
2.1 到此为止?
细心一点的读者可能发现,我们可能可以使用在算数・二项式系数与组合恒等式中提到的二项式定理来求解这个ex2.1,注意到
从而有
因而得到
而快速排序所得到的式子看起来更麻烦一些,因为其中有对数,但事实上这真是它简单的地方,因为我们知道
加以之前惯用的技术,我们有
经过略显繁琐的代数运算与系数比对,我们能够得到
这也揭示了快速排序的平均时间复杂度为
3.一般策略
很多时候,将一个复杂的生成函数展开为幂级数形式是非常困难的,这让人感到沮丧。不过,通过上面的计算我们发现,我们能够经常得到一些形如
幸运的是,混凝土数学(《具体数学》 by Knuth)上,有一个如下叙述的定理:
若生成函数
其中
但书中并没有给出证明,因此我试着证明了一下。
在初等的代数书中介绍了多项式的带余除法的概念,借助带余除法,我们知道上述有理函数
其中
由
因而将
逐项进行幂级数展开,则对于每一个展开式中的
即
因而我们能够知道其系数
而由
可以看出,对于每一个确定的
最终在
取
我们来简单演示一下这个定理的用法,譬如递推式
我们很容易就可求得其生成函数是
所以根据定理,我们知道对于某个常数
其中
再将
4.后记
生成函数是一项非常实用的工具,在这里我仅仅介绍了其冰山一角。更多的有关于生成函数的知识,只有等到我们遇到相关问题之时再做介绍了。
在这篇部分问题的解答过程中,我也曾走入歧途,一度执迷于创造新奇的方法而忽略了现有的工具,于定理证明上挣扎许久。实际上,如果你无法解出一个问题,那么要么是有一个更简单的问题你未能解决,要么是你仍有工具还未使用。