生成函数

这一页教你把一整条计数数列 编码进一个幂级数 ,然后用代数运算代替组合推理。学完之后,你能处理两类原本很绕的问题:带约束的选取计数(“苹果必须偶数个、香蕉至少一个”这类条件),以及求递推数列的通项公式。核心只有一句话:乘法就是分步计数,系数提取就是答案。

从一个念头开始

第 3 章的组合计数处理的是干净问题:无重复选取、恰好 个。现实里的计数问题总带着附加条件——每类物品的数量上限下限不同、总数不固定。条件一多,分类讨论很快就失控。

有一个想法可以避开这一切:与其逐个计算 ,不如把整条数列当作一个对象来研究。把 挂在 上做成幂级数,“恰好选 个”就变成了” 的系数”。约束条件则用级数的形状表达:只许偶数个,对应 ;至少一个,对应 。分步选择对应乘法,互斥情形对应加法——第 3 章的加法原理和乘法原理在这里升级成级数的加法和乘法。计数问题于是变成代数问题:因式分解、展开、读系数。

普通生成函数

数列 的普通生成函数(ordinary generating function, OGF)是幂级数

例如常数列 的生成函数是 ,等比数列 的生成函数是 。我们把 看作数列的一种”封装”, 是占位符而非未知数。

这里要立下一句话的规矩:本节把幂级数当作形式幂级数处理——只关心系数序列和系数的代数运算,不问 取什么值时级数收敛。收敛半径是分析学的课题,组合推理里完全不需要它。所有”令 足够小”的写法都只是习惯口头禅,你可以直接无视。

基本运算与它们的组合含义

每种代数运算都有一个组合解释,这是生成函数好用的根本原因。

加法。 的系数是 ,对应互斥的两类方案做并集——正是加法原理。

乘法(卷积)。 设 ,,则

内层那个和叫卷积。组合含义:完成一件事要分两步,第一步规模 有 种做法,第二步规模 有 种做法,对所有可能的 求和,就是”两步合计 个”的总方案数——乘法原理对所有分割方式的累加。这一条是全章的引擎。

移位与乘以 。 ,即整条数列下标加一、首项变零。组合上,“先固定垫一个,再从 个里选”对应的正是因子 ——所以约束”至少一个”由因子 表达。同理 是删掉首项。

求导与积分。 的系数是 ;反过来积分把系数除以序号。一个有用的组合是 ,即”带权计数”——每个方案按规模 加权。求导能把” 倍”这类权重搬进系数里,处理期望值相关的问题时会用到。

部分分式。 拿到有理函数形式的生成函数后,标准的拆项技术叫部分分式分解:把它拆成若干个 之和,每一项都认识。这是已知技术,本节只使用不展开。

常用级数库

下面五个级数是工具箱的常备件,系数提取全靠认出它们。

第一个是几何级数,第二个把 换成 。第三个是二项式定理, 为正整数时右边是有限多项式——它编码的是”从 个不同元素任选”的计数( 的系数就是 )。第四个值得多看一眼:把左边写成 个几何级数的乘积

的系数是”从 个括号各取一个非负幂次、指数之和为 “的取法数,也就是不定方程 的非负整数解个数——这正是第 3 章隔板法的结论 。隔板法在这里获得了一个新身份:它不是什么独立技巧,只是 的系数。

第四个级数的常见变体: 与 相等,两种写法都在用,提取系数时哪个顺手用哪个。

应用一:带约束的选取计数

例题 1. 一只水果篮装苹果、香蕉、梨三种水果,要求苹果装偶数个(可以零个)、香蕉至少一个、梨至多两个。设恰好装 个水果的装法数为 ,求 的生成函数,并算出 。

解. 逐类写出数量约束对应的级数:

  • 苹果偶数个:;
  • 香蕉至少一个:;
  • 梨至多两个:(有限多项式,上限约束直接截断)。

分步选择对应乘法,所以

求 只需把乘积算到 。先乘前两个因子:

其中 来自 , 来自 。再乘 , 的系数是

即前因子中 的系数分别乘 后相加。直接枚举验证:苹果 0 个时梨取 对应香蕉 ,有 3 种;苹果 2 个时梨取 对应香蕉 ,有 2 种;苹果 4 个时香蕉至少一个无法满足。合计 ,与系数一致。

这个例子的方法论值得记住:每类物品写一个因子(下限用 的幂垫位,上限截断,“恰好一类”用二项式),约束全部进因子之后,剩下的只是机械地乘开读系数。

应用二:用生成函数解递推

第 6 章用特征方程解常系数线性递推。生成函数给出同一条路的另一种走法,而且全程只做代数,不需要猜解的形式。流程固定三步:代入幂级数 → 解出 的代数方程 → 展开回系数。

例题 2. 解递推 ,初值 。

解. 设 。把递推两边从 起乘 再求和:

左边是 ;右边提出一个 ,余下的是完整的 ,即 。于是

认出 (级数库第二条,),乘上分子 2 得

迭代验证:,与 吻合。当然这个递推太简单,直接迭代就能猜出答案;生成函数真正的威力在下一步。

例题 3. 用生成函数求斐波那契数列的通项:。

解. 三步走完。

第一步:代入。 设 。把递推从 起乘 求和:

左边 。右边第一项提出 后下标平移,是 ;第二项提出 ,是 。

第二步:解代数方程。

第三步:展开回系数。 分母因式分解。令

则 ,,所以 。部分分式分解给出

(求待定系数:设 ,通分后比较常数项得 ,比较 项得 ,解出 。)

对两项分别用级数库第二条展开:

读系数,得到比内公式(Binet’s formula):

验算: 时 ; 时 。由于 , 指数衰减, 是离 最近的整数——无理数组合出整数列,这正是生成函数方法的标志性画面。

对比第 6 章的特征方程做法:猜 、解 、用初值定常数。两条路在代数上是同构的,特征方程的根 正是分母 的根的倒数。生成函数的优势在于不用猜——幂级数代入是机械步骤,且它统一处理计数与递推两类问题。

指数生成函数:一句话定位

指数生成函数(EGF)把数列除以阶乘再封装:。它的乘法对应带二项式权重的卷积 ,组合含义是”把 个带标号的元素拆成两组、分别计数再合并”——处理排列、错位重排这类标号问题时,EGF 是正确工具,本章不展开。

常见错误

在收敛性上卡住。 反复问” 取多少这个级数才收敛”是初学者最大的时间黑洞。形式幂级数的视角下, 只是系数的货架标签,所有运算只涉及有限次加法和乘法(提取 系数时,更高次项一律写成 扔掉)。需要分析收敛性的场合(渐近估计、鞍点法)超出了本章范围。

系数提取时数错。 乘积中 的系数是所有”因子指数凑成 “的取法之和,漏项、重复是最常见的错。两个补救办法:一是像例题 1 那样只保留需要的阶,把每个因子的级数在 处截断再乘;二是用独立方法(小规模枚举)核对头几个系数,对上了再推广。

移位时下标对不齐。 由 这类平移,最容易错的是初值项的处理:先把 对齐递推的起始下标,再提因子。例题 3 中左边是 而不是 ,就是因为 两项都要先摘掉。

练习

练习 1. 写出数列 ()的普通生成函数,并表示成有理函数形式。

答案:。由 ,得 。(提示:对几何级数求导再整理,也能得到同一结果。)

练习 2. 求 中 的系数。

答案:用级数库第四条,。组合验证:不定方程 的非负整数解数,隔板法给出 。

练习 3. 求不定方程 满足 ,, 的整数解个数。

答案:三个约束对应因子 、、,乘积为 。 的系数等于 中 的系数,即 (; 时为 0)。可用代换 化为标准隔板问题复核。

练习 4. 用生成函数解递推 ,初值 。

答案:设 ,代入求和得 ,整理:

(部分分式:解 ,得 。)展开得 。核对初值:,,且 显然满足递推。

学习路径