注:本篇文章是在我技艺尚不精时所写,有很多视角是过时的,而且很容易让自己搞混,请谨慎参考!
一点乱记,用于个人理解和巩固,亦可作为一篇学习顺序参考的文章。
如有笔误敬请指出。
二项式反演
组合恒等式
(nk)=(nn−k),n≥0,对称恒等式。
k(nk)=n(n−1k−1),k≠0,吸收恒等式。
(nm)(mk)=(nk)(n−km−k),组合意义易证。
∑k(rm+k)(sn−k)=(r+sn+m),范德蒙德卷积,组合意义易证。
求一列的前缀和:n∑i=m(im)=(n+1m+1),放在杨辉三角上易解释。
更多的可以去看具体数学(?)
例题一 ARC016F Card Game for Three
小 A,小 B,小 C 在玩游戏。他们每个人分别有 n,m,k 张牌,每张牌上面写着 a,b,c 三个字母中的其中一个,每个回合有一个人出牌,如果出牌为 a 则小 A 下一个回合出牌,如果出牌为 b 则小 B 下一个回合出牌,小 C 同理。若轮到某位玩家出牌时,其手中无牌,则该位玩家获胜。
现在小 A 第一个出牌,对所有 3n+m+k 种手牌拥有的可能性计算小 A 获胜的方案数,对 109+7 取模。
如果按照打出的顺序排成一个长度为 l 的序列,小 A 获胜当且仅当:a 恰好出现了 n 次且在最后一次出现,b 出现了不多于 m 次,c 出现了不多于 k 次。
而这个长度为 l 的序列对应了 3n+m+k−l 种手牌拥有的情况。
n 次是一定打的,枚举 b,c 出现的次数 t,然后枚举 b 出现的次数 i:
第一个组合数是除了最后一个是 a,确定 (n−1) 个 a 的位置,3m+k−t 是计算的对应了多少种手牌拥有情况,最后一个组合数为在 t 个 b,c 都可以填的空位挑出 i 个填 b,注意这个组合数可能会出现 i<0 或 i>t 的情况,由于是考虑其实际的组合意义,所以当出现这样的情况时视为 0.
最后一个实际上是组合数一行的区间和,众所周知这个的计算是困难的,由于这个区间和的形式比较特殊,考虑递推出这个东西:
至此,可以在 O(n+logmod) 的时间复杂度内解决问题。
二项式反演
形式一:
形式二(至多和恰好的转换):
形式三(至少和恰好的转换):
三种形式的证明类似,可以看 vfk 的PPT。
要区分这里的“至多,至少”和前缀和/后缀和对应的“至多至少”,二项式反演的“至多,至少”实际上是钦点一部分满足条件,其余部分随意,而前缀和/后缀和的“至多,至少”是钦点一部分满足条件之后,其他的必须不满足,所以前者是带一个二项式系数的。
例题二 BZOJ 3622 已经没有什么好害怕的了
先各自排下序,k←n+k2,其含义为要恰好有 k 对满足 a>b.
直接 dp 不太好做,因为如果状态设置为"前 i 个 a 匹配了 j 对 a>b" 的话,我们要考虑 b 中小于 ai 的个数 li 中有多少个数被之前选过了,然而只从 j 这一维无法体现这个信息。
所以就钦点 j 这一维表示 li 中有多少个 b 被之前的 a 选过了,只让 a 和小于它的 b 匹配,最后剩下的就让他们乱排,乘一个阶乘。由于最后乱排还可能匹配出 a<b 的,所以意义变为了至少有 j 对匹配了 a>b.
设 F(k) 为至少有 k 对 a>b,G(k) 为恰好有 k 对 a>b.
F 很容易 dp 出来,也就是:
其中 fi,j=fi−1,j+fi−1,j−1(li−j+1),分别表示 ai 进行匹配而是鸽到最后再匹配 和 ai 找一个比它小的 b 匹配。
考虑到:
很好理解,就是考虑这个“至少”的方案实际上有多少对 a>b.
二项式反演得:
问题解决。
莫比乌斯反演
欧拉函数
- φ(pk)=(p−1)pk−1
- φ(n)=n∏(1−1p),既可以从容斥原理角度考虑,也可以考虑直接利用 φ 为积性函数拆开对于每个素因子单独计算。
常用狄利克雷卷积
- 1∗μ=ϵ⇒∑d|nμ(d)=[n==1],考虑 μ(d)≠0 的 d,按照素因子个数分类在一起,再枚举素因子个数然后二项式定理;
- id=φ∗1⇒id∗μ=φ,考虑对 ≤n 且与 n 的 gcd 为 d 的正整数个数为 φ(nd);
狄利克雷前缀和/差分/后缀和/差分
感性理解一下,实际上问题就是关于质因数分解后指数的高维前缀和。
前缀和实际上是卷了一个 1,这个很好理解,因为式子一模一样。
前缀差分实际上是卷了一个 μ,因为 b=a∗μ⟺a=b∗1,而已知 a 求 b 实际上就是狄利克雷前缀差分。
狄利克雷前缀和
for(int i = 1; i <= pct; ++i)
for(int j = 1; j*p[i] <= n; ++j)
a[j*p[i]] += a[j];
狄利克雷前缀差分
for(int i = 1; i <= pct; ++i)
for(int j = n/p[i]; j; --j)
a[j*p[i]] -= a[j];
狄利克雷后缀和
for(int i = 1; i <= pct; ++i)
for(int j = n/p[i]; j; --j)
a[j] += a[j*p[i]];
狄利克雷后缀差分
for(re int i = 1; i <= pct; ++i)
for(re int j = 1; j <= n/p[i]; ++j)
a[j] -= a[j*p[i]];
更一般的,如果对于任意的积性函数,也有类似的方法。
设数论函数为 F,积性函数为 G,欲求 F∗G.
先把 F 拆分成若干之和质数 p 有关的积性函数 Fp 的卷积,即:
显然有 F=∏Fp.
把这些 Fp 分别卷到 G 上去即可求得答案。
对于每个 pk 枚举其倍数然后计算,预先存下需要用到的 G 即可。
这样复杂度为 O(∑n/pk),等比数列求和可得 O(∑n/pk)=O(n∑1p−1)=O(nloglogn).
例子 gcd 卷积
求 cn=∑(i,j)=naibj .
莫比乌斯反演易做到 O(nlogn)(?)这里可以用狄利克雷前缀和做到 O(nloglogn).
先求 c 的高维后缀和 c′n=∑n|(i,j)aibj 再狄利克雷后缀差分即可求得答案。
所以,将 a,b 作高维后缀和(狄利克雷后缀和),点乘后作高维后缀差分即可得到 c.
莫比乌斯反演
设 g(n) 为数论函数。
如果 f 为 g 的狄利克雷前缀和即:
则有:
证明: f=g∗1⇒f∗μ=(g∗1)∗μ=g∗(1∗μ)=g∗ϵ=g.
另一种形式:
如果有:
则有:
这里的 d 通常是小于等于一个界限,也就是题目中所给定的 "n"。
特别地,当 n=1 时,g(1)=∑μ(d)f(d),也可以理解为容斥系数为 μ 的容斥。
证明可以看 oi-wiki(
设 F(n)=exp(f(n)),G(n)=exp(g(n)) 对 (1) 式 exp,得到:
对 (2) 式 exp,得到:
也就是:
知道应该怎么推,避免遇到有 ∏ 的数论题直接抓瞎(
例题一
求长度为 n 且仅包含小写英文字母且循环节长度恰为 n 的字符串的个数。
n≤109.
设 f(n) 为长度为 n 的字符串个数,g(n) 为长度为 n 且最小循环节长度为 n 的字符串个数。
f(n) 是易求的,其为 26n.我们可以枚举最小循环节,用 g 来算出 f:
莫比乌斯反演得:
轻易解决。
例题二 Codeforces 1559E Mocha and Stars
对第三个条件进行莫比乌斯反演,得:
其中 f(d) 为 gcd 为 d 的倍数时的答案。
对于 f(d),每次可以做一下背包,用前缀和优化易做到 O(nmd),总时间复杂度就是 O(nmlognm),注意到 μ(d) 为 0 的时候不用跑背包,所以这个远远跑不满。
斯特林反演
第一类斯特林数
s(n,k) 为把 n 个数分成 k 个无区分轮换的方案数,也可以表示为 [nk]。
特别地:
- [n0]=0,n>0;
- [00]=1:我们假装只有一种方法可以把一个空集钦点成零个非空轮换。
第一类斯特林数有递推式:
考虑组合意义,n 是单独一个轮换还是和前面分在一起。
考虑组合意义,1 所在的轮换的大小是 i.
第一类斯特林数 · 行
设 Gn(x)=∑i[ni]xi,则根据递推式有 Gn=xGn−1+(n−1)Gn−1=(x+n−1)G+n−1,展开之后得到:
显然可以分治 + FFT 在 O(nlog2n) 来求得 Gn,也可以倍增 + FFT:
假设现在已经求出了 Gn(x)=∑aixi,想要求得 G2n(x):
这样两次卷积就能求出 G2n(x),复杂度为 T(n)=T(n/2)+O(nlogn)=O(nlogn).
多项式技巧不精,第一类斯特林数 · 列待填坑。
第二类斯特林数
S(n,k) 为把 n 个数分成 k 个无区分集合的方案数,也可以表示为 {nk}.
特别地:
- {n0}=0,n>0;
- {00}=1:我们假装只有一种方法可以把一个空集钦点成零个非空部分。
第二类斯特林数有递推式:
考虑组合意义即可,n 是单独一个集合还是分在前面的集合中。
考虑组合意义即可,i 为枚举的 1 所在的集合大小是多少。
第二类斯特林数通项 / 第二类斯特林数 · 行
有一个恒等式:
考虑组合意义即可,左边是 n 个球放入 m 个可空盒子的方案数,右边是枚举非空的集合数,亦可以用数学归纳法证明。
二项式反演得:
进一步转化可得:
这样就化成了一个卷积的形式,可以 O(nlogn) 求得所有的 {ni}.
多项式技巧不精,第二类斯特林数 · 列待填坑。
上升幂与普通幂
在 "一行第一类斯特林数求和" 中提到过上升幂转普通幂:
另有普通幂转上升幂:
数学归纳法易证。
下降幂与普通幂
在 "第二类斯特林数通项 / 一行第二类斯特林数求和" 中提到过普通幂转下降幂:
另有下降幂转普通幂:
数学归纳法易证。
不用数学归纳法?显然有 xn––=(−1)n(−x)¯¯¯n(直接拆开易证),代入到 (3) 得 (2),代入到 (4) 得 (1).
反转公式
将 (4) 代入到 (3) 得:
对比系数可得:
同理,把 (1) 代入 (2) 可得:
把 (2) 代入 (1) 得:
把 (3) 代入 (4) 得:
有的地方将 (5),(7) 称为反转公式,有的地方将 (6),(8) 称为反转公式,在此并不继续深究。
斯特林反演
证明一下 (9):
(10) 的证明类似,证明思路大概是:找到一个 “if”,说一句废话,把式子代入,交换求和号,整理一下。
通过前面二项式反演的证明以及后面提到的反演的证明更加体现了这个思路。
前面证莫比乌斯反演也是可以这么证的,不过用狄利克雷卷积更简单我就用狄利克雷卷积证了。
例题一 HDU 4372 Count the Buildings
n 前面有 F−1 个前缀最大,n 后面有 B−1 个后缀最大,那么把每一个前/后缀最大及其前/后面一段没有碰到前/后缀最大的看成一段,发现是钦定这一段让最大值排最前面,所以这些方案数是 [n−1F+B−2],然后选出 F−1 个放在 n 前面,答案为 (F+B−2F−1)[n−1F+B−2].
例题二 HDU 7095 / 2021 年百度之星·程序设计大赛 - 复赛 B Add or Multiply 1
你有一个数字 x 和若干个操作,每个操作是 +ai 或者乘 ×ai 中的一种。你可以重新排列这些操作的顺序,然后对数字 x 执行这些操作。
比如说三个操作是 +a1,+a2,×a3。如果按顺序执行这三个操作,那么得到的结果是 ((x+a1)+a2)×a3。如果排列成 +a2,×a3,+a1,那么得到的结果是 ((x+a2)×a3)+a1。
我们会发现,有一些操作顺序计算出来的结果是本质相同的,比如说 +a1,+a2,×a3 和 +a2,+a1,×a3这样运算下来结果是一样的。我们认为两个操作顺序计算的结果本质相同,当且仅当无论代入什么数,计算出来的结果都是一样的。
请问有多少种本质不同的操作序列。换句话说就是最多能找到多少个操作序列,使得这些操作序列任意两个都不是本质相同的。由于答案很大,输出对 109+7 取模的结果。
在这个题目中,我们只会给出加法操作和乘法操作的个数,分别是 n,m,并不会给出具体的顺序和数字。容易发现,答案与具体的顺序和数字无关。
共 T 组询问,1≤T≤104,1≤n,m≤3000.
把 x 个有标号球放进 y 个有区分非空盒子方案数 = y!× 把 x 个有标号球放进 y 个无区分非空盒子方案数 = {xy}y!,设其为 calc(x,y).
其中 {xy} 为第二类斯特林数。
考虑枚举有 i 个连起来的乘法块,那么其方案数为 calc(m,i).
i 个乘法块形成了 (i+1) 个空隙,两边的 2 个可空,中间的 (m−1) 个非空。
n 个加法有三种方法:
-
只放中间 (m−1) 个(钦点两个可空的都不放):calc(n,i−1);
-
钦点一个可空的为非空的,另一个不放:calc(n,i)×2;
-
钦点两个可空的为非空的:calc(n,i+1).
故答案为
时间复杂度为 O(m2+Tm).
例题三 「TJOI / HEOI2016」求和
求:
f(n)=n∑i=0i∑j=0{ij}2jj!mod9982443531≤n≤105
第二类斯特林数看起来就不好处理,考虑用第二类斯特林数通项公式把 {ij}j! 换掉:
注意最后一步等比数列求和当 k=0,1 的时候需要特判掉。
把仅关于 j 的提出来,仅关于 k 的合并,仅关于 (j−k) 的合并,整理成卷积的形式:
快乐 FFT,复杂度 O(nlogn).
例题四 TopCoder 13444 CountTables
设 g(m) 为 n 行 m 列的矩阵,满足任意两行不相同的方案数,则有 g(m)=cm(cm−1)(cm−2)...=(cm)n––.
设 f(m) 为 n 行 m 列的矩阵,满足任意两行两列都不相同的方案数,则有:
也就是划分成 i 个集合,每个集合里面都用一样的列。
斯特林反演一下得到:
例题五 Crash 的文明世界
给定 n 个点边权均为 1 的树和非负整数 m,对于每个点 i 求出:
n∑j=0dist(i,j)m对 104+7 取模。
n≤5×104,m≤150
暴力 点分治+FFT 可以做到 O(nlog2n)?
考虑普通幂转下降幂:
设 n∑j=0(dist(i,j)k)=fi,k,如果能对于每个 i 求得 fi,k 即可求得答案。
考虑固定 i 为根,此时的 j 的取值仅能为子树内点的编号。
此时只有根的答案是正确的,再换根 dp 即可。
时间复杂度 O(nm).
子集反演
众所周知,子集和超集本质上是相同的,只需要把每个集合看成自己的补集即可,同样有:
证明的基本思路和前面类似:
首先有:(枚举 |T| 之后就是 (1−1)|S|)
得证。
如果扩展到多重集合,如何构造容斥系数 μ 使得 ∑T⊆Sμ(T)=[S=∅]?
只需要让重复的元素都不起作用,对贡献为 0 即可,也就是 μ(S)=(−1)|S|[S中无重复元素].
于是:
注意到前文提到的 "莫比乌斯反演" 实际上就是把每个质因子看成一个元素,把每一个数看成一个集合,做这个多重集合的反演,本质上是相同的。
vfk的PPT 中提到了可以拿来算 and,or 卷积,仔细理一下会发现实际上就是 FMT / 高维前缀/后缀和。
FMT
试试从子集反演的角度理解 FMT。
给定长度为 2n 的数列 a,b,计算 c 满足:
n≤20.
也可以称之为 or 卷积?
把下标看成集合:
直接计算似乎很难,考虑计算出 c′n=∑u⊆ncu,然后把 c′ 还原成 c.
已知 a,b 求 a′,b′,可以用高维前缀和完成。
a 到 a′ 的映射就是 FMT 啦(
已知 c′ 求 c,就是高维前缀差分了,这个映射就是 IFMT。但其实也可以利用子集反演证明:
计算 and 卷积也同理,把子集换成超集再来一遍就可以了。
FWT
既然都说到了 FMT,自然要提提 FWT?虽然这个东西和子集反演没有什么关系(
回顾 FMT 的过程,实际上我们是构造了一个可逆的变换 F 满足 F(c)=F(a)⋅F(b),or 卷积是高维前缀和/差分,and 卷积是高维后缀和/差分。
给定长度为 2n 的数列 a,b,计算 c 满足:
n≤20.
感觉还是背柿子比较好,以后有了新的理解大概会回来更新(
A0 为 A 的偶数下标处组成的序列,A1 为奇数下标处,(A,B) 指的是将序列 A 和 B 拼接。
这个式子和 FFT 的很像。
通过 FWT 的式子易推得这个式子。
单位根反演
论文哥:感觉就像是把dft推式子证法中这东西抠了出来起了个名字。没在oi外的地方听说这东西还有类似这样的名字,像是近几年的oi造的名词。
记 n 次单位根为 ωn.
显然有:
等比数列求和,由于 vmodn=0 的时候公比为 1 要特判。
例题
LOJ6485 LJJ 学二项式定理
min-max 容斥
众做周知 max 和 min 是一样的,把优先级反过来即可。
现在证明上面那个式子,大体思路为:设出容斥系数,考虑每个元素是否能贡献列出式子,然后二项式反演得到容斥系数。
设容斥系数为 f,也就是 max(S)=∑∅≠T⊆Sf(|T|)min(T),钦点一个元素的编号为它的从小到大的排名,则排名为 k 的元素的是否能贡献为:
令 F(n)=f(n+1),G(n)=[n==0],则有:
二项式反演:
则 f(n)=(−1)n−1.
证毕。
如果左边的 max 是第 k 大,推导也同理,可得:
值得注意的是如果将 max/min 换成期望即 E(max)/E(min) ,也就是期望意义下的 min-max 容斥也是对的,形式化来讲:
设全集 U={X1,X2,...,Xn},其中 Xi 为互相独立的随机变量并且存在 E(Xi),则有:
max 和 min 互换,以及第 k 大的 min-max 容斥在期望意义下也成立。
证明很简单:
由期望的线性性可得:
例题
一个小例子
我们知道,若干个数的 gcd 相当于单独考虑每个质因子,在各个数里面的指数拿出来组成一个可重集然后取 min,最后再把每个质因子以及对应的次幂乘起来。lcm 也是同理,于是我们可以对这个指数组成的可重集进行 min-max 容斥来做到 gcd 和 lcm 的转换。
更具体地假如说有 gcd(S),lcm(S) 分别代表集合 S 中所有数的 gcd,lcm,则有:
gcd 转成 lcm 来也是同理。
例题一 HAOI2015 按位或
二进制为 1 的数位看成一个元素,每个数看成一个集合。
定义每个元素的权值为第一次变成 1 的时间,那么可以定义每个集合的 max,min.
所求即为 max(U),其中 U 为全集,现在要对任意一个集合 S 计算 min(S).
考虑枚举时间,计算其对期望的贡献。
定义一个集合 S 包含的元素的出现概率和(或者说与 S 有交的集合的概率和)为 pS,i 时刻第一次取到 S 中的元素,前 (i−1) 个时刻一定都没有取到 S 中的元素,则有:
其实就是每一步成功概率为 p,则期望成功步数为 1p.
pS 怎么求?注意到 x=1−pS 为所有与 S 无交的集合概率和,也就是其补集的子集和,高维前缀和计算即可。
Reference
具体数学 6.1 斯特林数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?