第一类斯特林数
第一类斯特林数定义如下:
(s_1(n,k))表示(n)个元素组成(k)个圆排列的方案数。
其中(n)个元素的圆排列定义为(n)个元素围成一圈的排列,两个圆排列本质相同当且仅当两个圆排列以任意方式旋转之后相同。
那么我们可以得到第一类斯特林数的递推公式:
这个很好理解,第一项是第(n)个元素单独组成一个圆排列,第二项是不单独组成,那么我可以把第(n)个元素放在任意一个元素的左边(右边),这里左边和右边其实是等价的。
这样求出(s_1(n,k))时空复杂度都是(O(nk))的,但是我们还有更优秀的做法:
考虑下面这个生成函数:
其中([x^k]F(x))就是(s_1(n,k))。
这个可以对照着前面的递推方程感性理解,基本上就是每乘一次((x+i))就表示从(s_1(n,k))转移到(s_1(n+1,k))。
那么我们就可以分治(FFT)优化到(O(nlog^2n))。
好像还有一种倍增的(O(nlog n))的做法先咕着以后再填。
例题:
[洛谷4609] [FJOI2016]建筑师,这个直接暴力递推就好了。
[CF960G] Bandit Blues,这个需要分治(FFT)。
第二类斯特林数
第二类斯特林数定义如下:
(s_2(n,k))表示把(n)个不同的元素放到(k)个无差别的盒子的方案数。
那么很显然我们可以得到递推式:
复杂度(O(nk))。
考虑一个比较有意思的东西,假设我们现在要算(s_2(n,k)),设(f(i))表示至少(i)个盒子空着的方案数,(g(i))表示恰好(i)个盒子空着的方案数。
那么我们可以得到:
对其广义容斥一下可得:
那么可以据此算出(s_2):
注意到这是个卷积的形式,所以我们可以在(O(nlog n))的时间内求出(s_2(n,i))的每一项,这里每一项指的是对于给定的(n),(iin [1,n])的每一项。
例题:
洛谷P4091 [HEOI2016/TJOI2016]求和,solution是很久以前写的了,不是很好看...还是放这里吧:sol。