跳到内容

6.3 生成函数:把计数序列编码成代数对象

补给方案的种类随着数量增长迅速失控,塔里的计数师把整列答案编码进一个幂级数。

当计数条件包含“每类可选若干个”“总数量恰好为 n”“多种组件组合”,逐项列举很快变乱。生成函数把一个序列放进幂级数的系数,使选择的组合变成多项式乘法。

普通生成函数

序列:

text
a₀,a₁,a₂,...

的普通生成函数(OGF):

text
A(x)=Σ_{n≥0} a_n x^n

x 主要是记录规模的形式变量,[x^n]A(x) 表示 x^n 的系数:

text
a_n=[x^n]A(x)

生成函数不是把序列值拿去逐个求函数值;它把整列系数打包,允许用代数运算操纵计数。

选择数量怎样变成多项式

一种组件可选 0、1、2 个:

text
1+x+x²

另一种可选 0 或 3 个:

text
1+x³

同时选择两类时相乘:

text
(1+x+x²)(1+x³)
=1+x+x²+x³+x⁴+x⁵

x⁴ 的系数为 1,表示总数为 4 有一种组合:第一类 1 个、第二类 3 个。

若不同来源能以多种方式贡献同一总数,乘法展开后同次幂系数会相加,自动完成计数。

无限几何级数

某类对象可选任意非负个:

text
1+x+x²+...=1/(1-x)

作为形式幂级数,这个恒等式来自:

text
(1-x)(1+x+x²+...)=1

若有 k 类对象,每类可选任意个:

text
1/(1-x)^k

x^n 系数是:

text
C(n+k-1,k-1)

这与隔板法得到的重组合公式一致。

硬币找零的生成函数

硬币面额 1,2,5,每种可用任意枚,按枚数组合且不计顺序:

text
G(x)=1/[(1-x)(1-x²)(1-x⁵)]

[x^n]G(x) 是凑成金额 n 的组合数。

若每种硬币最多一枚:

text
(1+x)(1+x²)(1+x⁵)

若 2 元硬币最多三枚:

text
1+x²+x⁴+x⁶

生成函数的每个因子直接表达局部选择限制。

注意:这里不计硬币排列顺序。若把 1+22+1 看作不同序列,需要另一种模型。

用生成函数解 Fibonacci 递推

定义:

text
F₀=0, F₁=1
Fₙ=Fₙ₋₁+Fₙ₋₂

令:

text
F(x)=Σ_{n≥0}Fₙxⁿ

n≥2 的递推乘 xⁿ 并求和:

text
F(x)-x = xF(x)+x²F(x)

所以:

text
F(x)=x/(1-x-x²)

对分母因式分解并做部分分式展开,可以恢复 Binet 公式。生成函数把递推关系转成代数方程,这是它在组合数学中的核心用途之一。

卷积对应独立规模的组合

若:

text
A(x)=Σa_nx^n
B(x)=Σb_nx^n

则:

text
[x^n]A(x)B(x)=Σ_{k=0..n} a_k b_{n-k}

右边是离散卷积:把总规模 n 拆成 kn-k,分别选择 A 类结构和 B 类结构。

解析树计数、括号结构、字符串拼接和动态规划中都能看到这种拆分。算法里的卷积还可用 FFT 等方法加速,但数值误差和模数选择属于后续主题。

指数生成函数何时出现

若对象带标签,普通生成函数常不能直接处理标签分配。指数生成函数(EGF)写作:

text
A(x)=Σ a_n x^n/n!

它适合排列、带标签结构和集合分拆等问题。OGF 与 EGF 的乘法规则编码不同的组合操作,不能因为名字相似混用。

本课只建立区分:

  • OGF 常用于按大小计数的无标签组合;
  • EGF 常用于带标签对象;
  • 具体使用由组合类结构决定,不是看到阶乘就机械选择。

软件中的状态计数

生成函数适合约束配置总量。例如 10 个插件中:

  • 每个基础插件可选或不选:因子 (1+x)
  • 某类插件最多选 2 个:因子 1+x+x²
  • 每个插件还有不同权重,可让指数记录成本而非个数。

但软件状态常存在依赖和互斥,不能把每个选项因子盲目相乘。若插件 B 依赖 A,可以:

  • 分类为“不选 A,也不能选 B”与“选 A,再决定 B”;
  • 构造有限状态自动机并使用转移矩阵;
  • 使用 SAT/SMT 或 BDD 统计满足赋值。

计数结果还可能把行为等价的配置重复计算。若要按对称性取商,需要群作用与 Burnside 引理等更高级工具。

从规模到测试策略

知道状态数巨大,只能证明穷举不现实。接下来还要:

  • 找出约束后的可达状态;
  • 按风险选择边界和代表类;
  • 用组合覆盖测试覆盖 t 路交互;
  • 用属性测试生成并缩小反例;
  • 对关键有限模型使用求解器或模型检查。

Pairwise 覆盖保证每对参数值至少共同出现一次,不保证发现所有三方或更高阶交互错误,也不证明系统正确。

完成检查

  1. 写出每种最多 3 个、共 4 种组件的 OGF;
  2. 求总共选择 5 个组件的方案数;
  3. 为面额 1、3、4 的硬币写出无限供应生成函数;
  4. 推导递推 a_n=2a_{n-1}+1 的生成函数;
  5. 为一个带依赖的插件配置解释为什么简单乘法会多算非法状态。

参考资料

Built with VitePress | Software Systems Atlas