斯特林数常用于各类计数问题中。

第一类斯特林数

记为,表示把个数分成个圆排列的方案数,有两个递推式:

第一个递推式的组合意义是枚举最后一个元素的选择;第二个递推式的组合意义是枚举第一个所在排列的状态。

生成函数

,那么根据的递推式有

因此可以得到

那么我们可以分治多项式乘法求出

第二类斯特林数

记为,表示把个数分成个集合的方案数:

相似地,可以从两个角度理解两个递推式。关于有一个恒等式:

组合意义:个不同的物品放到个不同的箱子里:

  • 左边:正常数法为
  • 中间:枚举有多少个非空盒子,那么我们先把个不同的球分成个非空集合,方案数为,然后再枚举这个盒子的位置。
  • 右边:和中间等价。

对上式使用二项式反演:

可以得到:

这个式子也可以用容斥理解。结合的组合意义,我们先假设集合有序。然后我们枚举有多少个空的集合,然后我们可以在剩下的集合中随遍填数。最后再除一个即可。

继续转化可以得到

这样可以使用多项式乘法计算。注意这个恒等式在的时候也成立(这时)。

代码

斯特林反演

首先,根据第一列斯特林数的生成函数有

根据第二类斯特林数的恒等式有

由于,那么同时代入并化简可以得到

结合可以得到

当然,结合同样可以得到

把结合的方式交换一下又是另一个关于上升幂或者下降幂的多项式,也对应了反演公式。综上:

如何应用斯特林反演?假设固定是常量,我们要求的是。那么等价于求。设

那么答案就是。而则需要通过其他的转化或者组合意义来求。

例题

Count the Buildings

求有多少个的排列满足前缀最大值的个数是,后缀最大值的个数是

除掉高度为的那个房子,剩下的我们可以把看得到的房子之间的部分与这些看得到的房子理解为一个圆排列。相当于这个组内的房子可以任意排列,但最高的那个一定要放在左边 / 右边,因此这是一个圆排列。于是容易想到第一类斯特林数。

具体地,我们把个房子分成个圆排列后,相当于要选择个放左边。因此总方案数为

代码

TJOI2016 求和

算法一

直接推。类似求第二类斯特林数的的公式,使用二项式反演展开,并整理成卷积的形式:

这样可以直接 FFT 了,复杂度

算法二

这个式子长得很奇怪。设

考虑其组合意义,相当于把个元素分成若干个集合,集合之间有序,并且每个集合有两种状态,问总方案数。考虑递推,枚举最后一个集合的状态,可以得到

稍作变换可以得到

这样就可以分治 FFT 了。时间复杂度

代码

算法三

by Entropy Increaser (origin)

仍然是推式子:

在算法一中,我们直接使用卷积完成了本题。但注意到,这是一个特殊的卷积。

对于生成函数,考虑

因此

不妨设。那么原式就变成了

那么只要我们能快速求出的各项系数即可。前者可以线性筛,后者可以递推(除以一个一次式)。因此时间复杂度就是的。

Crash 的文明世界

给一棵个结点边权为的树,对于每个求出

考虑到。因此我们考虑维护每个子树距离次方和用下降幂展开后的的系数,记为。则对于根结点,答案为。因此在此基础上换根即可求出答案。

考虑如何计算。考虑到

则对于若干条路径,对的贡献为

如果我们将他们都加 1,则贡献变成

而我们如果添加一条长度为 1 的路径,即把加入到序列中,则将会对都产生的贡献。可以理解为是路径数。因此我们得到了的转移式:

注意处理上边界的转移,对于子树中最长的链,要把长度的阶乘贡献到对应的 DP 值上。

然后再换根即可。

时间复杂度

代码

Partitions

给你一个长度为的序列,对于一个下标集合,定义它的价值

对于一个将划分到个集合的方案,记这个集合的集合是。那么这种划分的价值定义为

现在求的所有划分方案的价值和。

可以直接写出一个暴力式子:

两边可以分别计算。看到组合数和斯特林数的乘积,考虑将它转化为斯特林数递推式的形式:

这样只需要算两个斯特林数即可。时间复杂度

代码

图的价值

一个带标号的图的价值定义为每个点度数的次方的和。

给定,请计算所有个点的带标号的简单无向图(不一定连通)的价值之和。

对每个点的贡献分别计算:

这里我们考虑一个经典的套路:通常幂转下降幂(第二类斯特林数):(把减了

我们计算出即可。复杂度

代码

经典问题

个点条边带标号无向连通图的个数。

我们对连通块数做斯特林反演。设表示个点条边个连通块的方案数。那么答案就是

应用斯特林反演,设

答案是

考虑的组合意义:枚举,对于个点条边个连通块的方案,再把个连通块划分到个非空集合中。

这个组合意义等价于:枚举个点划分成个集合的方案,每个方案只能集合内连边,一共连条边的方案数之和。

又可以转化为:枚举个点划分成个集合的方案,每个方案总共有条可用边,那么这个方案的贡献是

考虑 DP。设表示个点有条可用边,划分成个集合的方案数。转移时枚举号点所在集合:

那么。这是个 4D/1D 的 DP,复杂度

考虑优化。

答案是

,则答案是

考虑求

如果系数是那么可以在转移的时候枚举任意集合,这样划分成个集合就被算了次:

如果系数是,就枚举号点所在子集:

因此为了让系数是,我们可以在求)的时候使用第一种转移,在求的时候使用第二种转移。这样就确保每个划分为个集合的方案,号点所在集合的位置是固定的,其他集合可以任意排列,也就是种方案。注意,这个方法不能做

异或图

定义两个结点数相同的图与图的异或为一个新的图, 其中如果中的出现次数之和为,那么边中,否则这条边不在中。

现在给定个结点数相同的图,设,请问有多少个子集的异或为一个连通图?

考虑容斥连通块的个数。

表示在所有连通块个数大于等于的方案(即异或出来的图)中,将连通块划分为个集合的方案数。定义比较奇怪,但考虑如何计算。

对于点集,考虑枚举所有的集合划分方案(方案数与贝尔数同阶),同一个集合内的点任意连通,而不同集合的点强制不连通。问满足这个条件的异或图的个数。

考虑线性基,我们只考虑跨过集合的边对应的位,把图插入到线性基中,问题转化为求异或和为 0 的方案数,显然为,其中表示线性基的大小。因为线性基外的图任意异或,都可以用线性基里的图唯一地异或出一个反图,使得异或和为 0。

于是我们枚举所有的集合划分方案,计算贡献,贡献到对应的上。这样就计算出了。我们现在要求的是,表示连通块个数恰好为的方案数(等价于在所有连通块个数等于的方案中,将连通块划分为个集合的方案数)。考虑到

根据斯特林反演得到

则得到

于是我们在实现的时候不需要斯特林反演,直接做即可。

时间复杂度

代码