整数分拆与 Ferrers 图
把正整数 写成若干正整数之和,且不计各加项的先后,每一种写法是 的一个分拆(partition),加项称部分(part),分拆的个数记 。,五种写法是 、、、、。同样叫「拆」,枚举全部划分拆的是一个由可辨元素组成的集合,块与块之间彼此不同;本页拆的是一个整数,元素不可辨,只有各部分的大小算数。两种口径的计数分别落在 Stirling 数与分拆数上,对照见Stirling 数。
1 · 有序和式与无序和式
若把次序也算进去, 与 记作两种,这样的有序和式称 composition。它的个数有闭式:把 摊成一排 个单位,相邻单位之间共 个空隙,每个空隙独立地断或不断,断点把这排单位切成若干段,段长依次就是各加项。空隙的断法与 composition 一一对应,故其数为 。这与可重复选取的隔板法是同一套构造,区别在于隔板法允许两根隔板重合而本节的断点两两不同,双射的一般写法见双射与双计数。
不计次序,就是把这 个 composition 按「排序后相同」归并成若干类,类数即 。 时 归并成 类; 时 归并成 类,比值随 迅速拉开。
2 · Ferrers 图与共轭分拆
把一个分拆画成点阵:一行一个部分,行内点数即该部分的大小,各行左对齐,自上而下行长非增。这张点阵称 Ferrers 图。沿主对角线转置,即把行读成列,得到的仍是一个行长非增的点阵,它所对应的分拆称共轭分拆。
定理 2.1 转置是 的分拆集合上的一个对合双射;恰有 个部分的分拆数,等于最大部分为 的分拆数。
证明 转置后第 行的点数,是原图中长度不小于 的行数,这个量随 非增,且总点数不变,故转置把 的分拆映到 的分拆。逐点看,转置两次每个点回到原位,所以转置是自身的逆映射,为对合,从而是双射。原图的行数在转置后成为第一行的长度,原图第一行的长度成为行数:部分数与最大部分互换。把这个双射限制在「恰有 个部分」的分拆上,像集恰是「最大部分为 」的分拆,两者等势。∎
本页 conjugate 按列计数实现:结果的第
项取原分拆中大于
的部分个数。这个写法对输入是否已排序并不敏感,conjugate([1, 3]) 与 conjugate([3, 1]) 同样给出
;代价是对合性只在非增输入上成立,把乱序的 [1, 3] 转置两次得到的是
而非原序列。测试里为这条行为单列了一项断言,免得后来者把它当缺陷「修好」。
3 · 分拆数的递推
没有初等闭式。实用算法给最大部分设一个上限:记 为最大部分不超过 的分拆数,按「有没有用到大小为 的部分」分类,用到则去掉一个仍留在同一上限下,没用到则上限降为 :
边界是 与 ,答案取 。滚动成一维后,外层枚举部分大小、内层正序枚举剩余量,与完全背包的一维递推逐字相同:一件物品可取任意多件,对应一种大小可以重复使用。生成函数的写法是 ,其中 的系数即 ,展开见生成函数。增长上,Hardy–Ramanujan 渐近式给出 ,是次指数的。
警示 · 一维 DP 若用 number 累加,第一处失真出现在
:精确值
是首个越过 Number.MAX_SAFE_INTEGER 的分拆数,浮点累加给出
,小
,而
仍逐位精确。枚举失效得更早:本页 partitions 列出
条约 56 ms、
条约 1.2 s,
是
的九百三十三倍,只能计数不能列举。图 2-1 据此把
限在
,并只渲染前
条。
4 · 参考文献
- Partition (number theory). Wikipedia. 分拆数 、Ferrers 图与共轭分拆的基本性质。https://en.wikipedia.org/wiki/Partition_(number_theory)
- Composition (combinatorics). Wikipedia. 有序和式及其 的计数。https://en.wikipedia.org/wiki/Composition_(combinatorics)
- Pentagonal number theorem. Wikipedia. 欧拉五边形数定理给出的 快速递推。https://en.wikipedia.org/wiki/Pentagonal_number_theorem