对于序列 {fn} 和 {gn},通过 f 计算出 g 叫做正演,通过 g 计算出 f 叫做反演。
二项式反演讲的是:
gn=n∑i=0(ni)fi⇔fn=n∑i=0(−1)n−i(ni)gi
将组合数展开得到:
gn=n∑i=0(ni)fi⇔gn=n∑i=0n!i!(n−i)!fi⇔gnn!=n∑i=01(n−i)!fii!
考虑序列 {fn},{gn} 的指数生成函数 F(x),G(x)。上式是一个卷积的形式,写成指数生成函数就是 G(x)=exF(x)⇒F(x)=1exG(x)。
将 e−x 在 x=0 处泰勒展开得到 e−x=∑ni=0(−1)ixii!,和 G(x) 卷起来得到
F(x)=n∑k=0k∑i=0(−1)k−i1(k−i)!gii!xk⇒fnn!=n∑i=0(−1)n−i1(n−i)!gii!⇒fn=n∑i=0(−1)n−in!i!(n−i)!gi=n∑i=0(−1)n−i(ni)gi
证毕。
错位排序#
求满足 ai≠i 的 [1,n] 的排列数。
设 D(n) 表示长度为 n 的序列的错排数,通过枚举错排位置可得:
n!=n∑i=0(ni)D(i)
显然可以二项式反演,得到:
D(n)=n∑i=0(−1)n−i(ni)i!=n∑i=0(−1)n−in!i!(n−i)!i!=n∑i=0(−1)n−in!(n−i)!=n!n∑i=0(−1)i1i!
第二类斯特林数#
第二类斯特林数 {nk},表示将 n 个互不相同的元素分成 k 个互不区分的非空子集的方案数。
- 注意到这里元素互不相同,所以不可以直接插板!
- 以下内容可以直接使用容斥原理直接得出。
定义 gn 表示允许空集的方案数,fn 为不允许空集的方案数(此处集合互相区分),显然,每个数都有 k 种选择,共 kn 种。
枚举 k 个集合中的空集,剩下的非空,加起来得到 gn,即:
gk=k∑i=0(ki)fk−i
对其进行二项式反演,得到:
fk=k∑i=0(−1)k−i(ki)gi=k∑i=0(−1)k−ik!i!(k−i)!in
由于这里 fn 集合是相互区分开的,我们最后要除去集合间的排列,得到
{nk}=fkk!=k∑i=0(−1)k−iini!(k−i)!=k∑i=0(−1)k−i(k−i)!ini!
注意到这里还是个卷积,可以跑多项式 O(nlogn) 求。
将这个式子带回,得到
gk=kn=k∑i=0k!i!(k−i)!{nk}i!=k∑i=0Pkn{nk}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现