第一类斯特林数
定义是 n 个数,m 个圆排列
Θ(n2) 的 dp 是:Si,j=Si−1,i−1+Si−1,j×(i−1)
如果预处理一行的话需要这个式子:
x¯¯¯n=n−1∑i=0[ni]xi
分治乘法做到 Θ(nlog2n),更快的部分需要倍增
也就是 x¯¯¯¯¯¯2n=x¯¯¯n(x+n)¯¯¯n
考虑 f(x) 来推 f(x+c) 是可以做的,那么直接两个卷积即可
注意减法卷积贡献到的位置,是 len+i+1
对于求一列的情况,考虑 EGF:S1 的 EGF 是 ∑ixii
对于多个圆排列就快速幂一下,最后要除掉圆排列个数因为其本质相同
写一个 ln+exp 即可
第二类斯特林数
定义第二类斯特林数 S(n,m) 为将 n 个球放到 m 个盒子里的方案数,球不同,盒子相同
然后容易由 dp 得到一个递推式
S(n,m)=S(n−1,m−1)+m×S(n−1,m)
按照组合意义:容斥有多少个盒子是空的
S(n,m)=1m!m∑k=0(−1)k×(mk)×(m−k)n
把式子推一下
S(n,m)=m∑k=0(−1)kk!×(m−k)n(m−k)!
这里是个卷积,预处理阶乘,逆元就做完了
第二类斯特林数的一个性质:
nk=k∑i=0S(k,i)×i!×(ni)
也可以导出:
n∑i=1(ni)ik=k∑i=12n−i(ni)S(k,i)×i!
直接上组合意义,左边是在 n 个互不相同盒子里面放 k 个小球的方案
右边是枚举盒子的数量,放在哪几个盒子里面,然后因为盒子不一样,然后就在来个阶乘就没了
如果是求一列,考虑设第 i 列的普通生成函数为 Si(x)
不难观察到其只和自己和上一列有关,递推式就是 Si(x)=mx×Si(x)+Si−1(x)×x
不断迭代下去得到
Si(x)=xm∏mi=11−ix
分治乘法加求逆即可,也可以按照 EGF 来做
斯特林反演:
若
f(n)=∑i(−1)i{ni}g(i)
则
g(n)=∑i(−1)i[ni]f(i)
将排列斯特林数和组合斯特林数调换位置也是正确的,这个使用结论:
[m=n]=(−1)n∑i(−1)i{ni}[im]
或者
[m=n]=(−1)n∑i(−1)i{im}[ni]
可以证明,而这两个结论使用上升下降幂公式硬上,发现对于多项式系数必然一致,那么证毕
然而本题中并不使用上面的式子,而是考虑:
f(x)=n∑i=x{ni}g(i)
可以得到
g(x)=n∑i=x[ni](−1)i−xf(i)
证明是类似的,本质上是一个上三角变成了下三角
例题
HEOI2016 求和
首先把三角转成矩形,然后套上 第二类斯特林数的组合公式,每一步都找无关量,最后推等差出来卷积即可
Θ(n) 的做法当然不是现在学的
「Luogu4827」 Crash的文明世界
记住这个关键的式子:
nk=k∑j=0{kj}j!(nj)
使用人类智慧,把最后的组合数用杨辉三角展开(其实用“如何转移”的思路也可以得到)
那么设 fx,i 表示 x 为根的时候子树里面 (disi) 的和
换根统计即可
FJOI2016 建筑师
一定能看到最高的那个楼,所以该正反的序列就都以高度为 n 的为结尾
然后就是在剩下的 n−1 个里面选 b−1 个构成下降序列扔后面,选 f−1 个构成上升序列扔前面
所以这 n 个数被分成若干个圆排列
再想上这几个组再组合一下可以分成前面的 f−1 个和后面的 b−1 个,所以
ans=((b−1)+(f−1)f−1)×S(n−1,(b−1)+(f−1))
O(n2) 预处理斯特林数,和组合数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律