组合计数课程笔记(二):十二重计数法(初等计数)

组合计数问题是组合数学中重要的最古典的分支。有人将组合计数问题归为 12 个集合映射问题。但是其中有 2 个是平凡的,所以我们只研究 10 个。

十二重计数法

在数学上,严谨的定义是“从一个集合对另一个集合的映射的个数”。但是我们可以用更简单的方法定义它:把 n 个苹果装进 m 个盒子的方案数。

首先,我们根据集合的性质来进行分类。对集合 S,如果在映射的过程中,我们令打乱 S 中的数的顺序后得到的映射和原先的映射是等价的(也就是,在群的形式下,两个映射函数形成等价关系),我们就可以把 S 中的数划分为同一个等价类,这时我们称 S 中的元素是不区分的。也就是,所有的苹果 / 盒子都是相同的。因为有两个集合 NM,所以一共能分 4 种。

其次,我们按照映射的性质来分类,分为“不受限”“单射”和“满射”。也就是,每个盒子随便装、最多装一个、最少装一个。

这样,我们列出一张 34 的表,表示所有 12 种问题。不过其中有 2 个是平凡的。分别是 XI 和 VIII。

N M 不受限 单射 满射
区分 区分 I: Tuple II: Permu III: Stir
不区分 区分 IV: w-Comp V: Binom VI: Comp
区分 不区分 VII: Stir VIII: Ordin IX: Stir
不区分 不区分 X: GF XI: Ordin XII: GF

计数公理

映射法则

对于集合 ST,其中若存在映射 f:ST 满足:

  • f 是单射,则 |S||T|

  • f 是满射,则 |S||T|

  • f 是双射,则 |S|=|T|

法则本身的内容只涉及第三条,剩余两条是补充的。其意义在于如果两个集合中的所有元素一一对应,则两者元素数量相同。

实际上,双射法则常常出现在很多的定义中,

乘法法则

不同的代数对象有不同的乘法法则,例如生成函数中的乘法法则就和集合计数的乘法法则不同。

两个集合的笛卡尔积 S×T 的定义是 {(a,b)|aS,bT}

|S×T|=|S||T|

乘法法则的应用情形是比较好判断和容易使用的。

加法法则

两个不相交的集合 ST|ST|=|S|+|T|

加法法则则不好运用,因为其满足的条件相较苛刻,应用情形难以直观看出,更具技巧性。

组合数

子集总数

组合数是有穷集合的子集。

定义 [n] 的幂集 2[n]={S|S[n]}

我们证明 |2[n]|=2n

组合的证明方法是把 S 表示为一个长 n0/1 特征向量(编码集合)。

具体而言,对于 i[n],如果 iS,则特征向量的这一位是 1,否则是 0。我们从而建立了特征向量和子集的双射。而特征向量是 {0,1}n,根据乘法法则,就是 2n

或者,我们定义 f(n)=|2[n]|,然后把 2[n] 表示成 {S[n]|nS}{S[n]|nS}

则前后无交集且存在双射,都是 2[n1]

所以 f(n)=2f(n1)

而且 2=1 是良定义的,所以 f(n)=|2n|

现在我们在解的是比较简单的线性递推式,那么别的线性递推呢?例如 f(n)=a1f(n1)+a2f(n2)++akf(nk)+a0

这就需要使用生成函数的知识解决,例如我的这篇博客讲解了斐波那契数列的通项。

子集

我们定义 k-uniform(Sk)={TS| |T|=k}。它涉及到 k-complete hypergraph 的一些内容。

十二重计数法

I: Tuples

我们定义 [m] 是小于等于 m 的正整数的集合,那么 [m]={1,2,,m}

根据乘法原则,它的 n 次笛卡尔积 [m]n 的大小 |[m]n| 就是值域为 [1,m]n 元组的个数。

那么我们定义 f:[n][m],找到 f 的真值向量 (f(1),f(2),,f(n)),这个向量的集合就和映射的集合建立了双射。同时它还和值域为 [1,m]n 元组建立了双射。

那么,映射的个数就是 mn

II: Permutation

我们还是找到 f 的真值向量 (f(1),f(2),,f(n)。但是因为是单射,所以 (f(1),f(2),,f(n)) 是一个排列 π,它是 [m]n 的一个子集。

我们考虑别的方法,我们发现,确定第一位的时候有 m 种,第二位有 m1 种……最终一共有 m(m1)(m2)(mn+1) 种。我们记作 (m)n,或者 mn,也就是 mn 次下降幂。

至于严格论证,我们需要链式法则,它不包含于上述法则中,因为它是另一种积而非笛卡尔积,涉及条件概率。

III: Stirling

先看 IX: Stirling

然后,我们发现这是一个满射。满射具有什么样的性质呢?对于满射 f:[n][m],存在逆射 f1 满足对任意的 i[m]f1(i) 并且 f1(i)f1(j)=f1(i)=[n]。我们发现,如果我们忽视 f1(i) 之间的区别,它其实等价于一个 nm 的集合划分问题。

那么,假设我们找到了集合划分问题的一组解 F={f1(1),,f1(m)},我们只要乘上一个 π,构成一个笛卡尔积集合 (F,π),就和原来的映射构成一个双射,那么根据乘法原则,答案就是 m!{nm}

IV: weak k-composition

先看 VI: composition

然后,我们构造 IVVI 的双射。在 weakkcomposition 的解决过程中,我们其实在求 k=m 元组满足xi=n,xiN。和 k-composition 唯一的不同就是允许有 0,那么我们就考虑把 0 去掉,也就是构造双射 ϕ((x1,x2,,xk))=(x1+1,x2+1,,xk+1)。这 k 个数的和是 n+k,而 1。两者的双射关系是显然的,则答案即为 n+kkcomposition,即 (n+k1k1),也记作 ((nk))

V: Binom

我们知道,有序的 k 元子集个数是 (n)kbyII),而对 k 个不同元素的排列运算 π 一共有 k! 个。

那么,我们假设集合 n 的无序 k 元子集的集合是 R,而排列运算的集合是 π,那么构成的笛卡尔积集合 (R,π) 和有序 k 元子集 R 构成一个双射。

那么,应用乘法原理和双射原理,得到 |R||π|=|S|。解出 |R|=(n)kk!

我们就定义 (nk)=|R|=n!k!(nk)!,这就是组合数。

  • n 元集的所有子集 S 到每个 S 的补集形成双射,所以 (nk)=(nnk)

  • Ti 表示 S 的大小为 i 的子集的集合,那么 i[0,n]Ti=2S。所以 i[0,n](ni)=2n

二项式定理

(1+x)n=(1+x)(1+x)(1+x)=(nk)xk

这个可以通过简单的在中项中选 k 个来表示。同时,这也给出了 i[0,n](ni)=2n 的另一种证明。

通过二项式定理,如果我们令 x=1,那么 i[0,n](ni)(1)i=0,也就是 i(ni)(1)i=i(ni)(1)i。也就证明了大小为奇数的子集个数等于大小为偶数的子集个数。

二项式定理的最大的意义在于,我们用加法和乘法这样基础的代数运算的有机结合,创造出了复杂特殊的具有组合意义的组合数。这种用简单运算组合生成想要的量的思想,为生成函数的涌现埋下了刚刚生出的幼芽。

VI: composition

找到问题 VI 的解,等价于找到一个 k=m 元组 (x1,x2,,xk) 满足 x1+x2++xk=nxiZ+

它属于一个巨大类问题的特殊形式:线性规划。

整数线性规划是给定 k 个变量,若干个不等式,求其整数解的数量。其实就是在 k 维空间中,在划定的一个凸多面体中寻找整点的个数。这个问题是 NPhard 的。不过这个问题显然非常特殊,因为它只有一个等式(相当于两个不等式)。

我们可以用插板法。更加严谨的证明,我们需要构造双射。

ϕ((x1,x2,,xk))=(x1,x1+x2,,x1+x2++xk)

明显的,右边的每个数都不同,并且都小于 n。并且 ϕ 是一个双射。而右边其实就是 n1 的一个大小为 k1 的无序子集,所以等于 (n1k1)

VII: Stirling

先看 IX: Stirling

然后的部分非常简单,我们枚举有多少个集合是空的,答案就是 im{ni}

VIII: Ordin

这个问题是平凡的,答案为 [nm]

IX: Stirling

这个问题等价于集合划分,也就是对 S,找到 S1,S2,S3,,Sk,满足 SiSj=(ij),Si,且 Si=S

我们也将这个问题称为 n 元集的 k-partition。我们定义第二类斯特林数为 {nk},也就是把 n 个不同的元素划分到 k 个集合的方案数。

同时,还有 all-partition 问题,这个问题的答案是 Bn=kn{nk},又称贝尔数.

第二类斯特林数有一个递推公式,通过简单的 dp 就可以得到,{nk}=k{n1k}+{n1k1}

X: GF

先看 XII: GF

然后我们枚举几个划分是 0,答案是 ikpi(n)

XI: Ordinary

VIII 一样,这个问题是平凡的,答案是 [nm]

XII: GF

无序的整数划分,也就是找到一组 (x1,x2,,xk) 满足 x1+x2++xk=nxiZ+x1x2xk

我们设 pk(n) 为把 n 划分成 k 个正整数的方案数,然后根据 xk 进行讨论。

  • 如果 xk=1,我们去掉 xk 并不会影响答案

  • 如果 xk>1,所有的 xi 都大于 1,把它们都减掉 1 (和减去 k)也不会影响答案。

所以 pk(n)=pk1(n1)+pk(nk),得到了一个递推式子。

我们想办法逼近一下 pk(n)

首先,用 x1,x2,,xk 构造一个满射,这个满射是 (x1,x2,,xk,π)(x1,x2,,xk),也就是 k-composition。我们把 x1,x2,,xk 任意排列都会得到一个 k-composition

也就是 (x,π)x。由满射原理得 |S||T|,即 k!pk(n)(n1k1)

然后再构造一个单射,我们发现,如果我们把 xi 加上 ki 的话,序列变得单调不降。并且满足单射条件。而如果单调不降,就又可以双射到 kcomposition

在构造的过程中,我们一共给数加上了 k(k1)2,所以由单射原理得 k!pk(n)(n+k(k1)21k1)

由此又得到 (n1k1)k!pk(n)(n+k(k1)21k1)k!。而若 k 是常数,n,则 pk(n)nk1k!(k1)!

实际上,这个范围就是初等计数所能达到的终点了,它象征着一个时代的终点,用一把斧头就能劈开前路的情况已然不再,没有舟船,谁也无法度过汪洋大海。

你只得到此,不能逾越

拉努马金的研究告诉我们 p(n)=pk(n)14nexpπ2n3

OI 中,想要计算划分数,需要用到 GF Girl Friend Generating Function

埋下的种子将发芽。

相关的其他计数

可重集的 k 元子集

我们现在有一个集合 {1,2,3,4},它的大小为 3 的子集是 {1,2,3}{1,2,4}{1,3,4}{2,3,4}

但是,如果我们需要的是它的可重子集呢?那就可以是 {1,1,1}{1,1,2} 等等很多的答案。

要计算可重子集的个数,先要明确可重集的定义。

可重集是从集合 SN 的一个映射。

我们可以用 0/1 串来表示子集,也就是 xi 表示 S 中的第 i 个数是否出现在子集中。这是从 S{0,1} 的映射。那么从 SN 的映射就是 m(i) 可以为任意的正整数,子集的大小就是 m(i)

我们发现,这个求可重集的 k 元子集个数,就是 m(i)=k,m(i)N,等价于十二重计数法之 IV。答案就是 (n+k1k1)

多项式系数

我们考虑多重集 S 的排列。如果我们将其可视化,就是若干个可重的字母,求其排列个数。

形式化的,对于集合 TN 的映射一个映射 m(i),求其排列个数。我们可以先计算 |S| 的全排列 n!。在每个排列中,每个字符之间的全排列都是等价的,也就是对于 im(i)! 个排列等价,那么最终的答案就是 n!m(1)!m(2)!m(3)!m(k)!,记作 (nm(1),m(2),,m(k))

同时,有多项式定理:(x1+x2++xk)n=m1+m2++mk=n(nm1,m2,,mk)x1m1x2m2xkmk

这也是一种形式的代数生成。

posted @   jucason_xu  阅读(384)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示