# 二项式反演
# 公式
fn=i=0∑n(in)gi⇔gn=i=0∑n(−1)n−i(in)fi
证明就不细说了。那么二项式反演的式子有什么用呢?
恰好和至多的转换:
设 fk 为恰好 k 个的方案数,gk 为至多 k 个的方案数(恰好 k 个和至多 k 个均为某种条件)。
假设可以快速计算出 gk,我们要通过 gk 计算 fk。
可以知道,gk=i=1∑k(ik)fi
(枚举恰好 i 个满足条件,有 k 选 i 种方案,加起来)
根据二项式反演可以得出:
fk=i=1∑k(−1)k−i(ik)gi
恰好和至少的转换:
同理,设 fk 为恰好 k 个的方案数,gk 为至少 k 个的方案数。
有:
gk=i=k∑n(ik)fi
根据二项式反演:
fk=i=k∑n(−1)i−k(ik)gi
# 例题
# P4859 已经没有什么好害怕的了
首先对 a,b 从小到大排序。
设 dpi,j 表示前 i 个 a 中,至少有 j 对 a>b,考虑如何转移。
分两种情况:
ai 对 j 没有贡献,那么加上 dp_
ai 对 j 有贡献,那么加上 dpi−1,j−1×(pi−(j−1))。pi 为最小的 ai>b 的 b 的位置,由于 b 是有序的,所以 pi 也是单调不降的。
写到一起:
dpi,j=dpi−1,j+dpi−1,j−1×(pi−(j−1))
计算出 dp 数组之后。设 gi 表示至少有 k 对 a>b 的方案数,即等于 dpn,k×(n−k)!。
乘上 (n−k)! 是因为其他的可以随便排,只要保证至少有 k 对 a>b 即可。
再设 fk 表示恰好 k 对 a>b 的方案数,那么有 gk=i=k∑n(ki)fi
根据二项式定理:
fk=i=k∑n(−1)k−i(ki)gi
然后就可以计算出 fk 了。
需要注意的一个点,由于题目中要求的是 a>b 的对数减去 a<b 的对数为 k,所以 a>b 的对数为 2n+k。
# 斯特林数
# 第一类斯特林数
[kn] 表示将 n 个不同的数划分为 k 个圆排列的方案数。
递推式:
[kn]=[k−1n−1]+(n−1)[kn−1]
第 n 个数单独一个圆排列,或者与前面的原排列合并到一起,放到任意一个数后面都行,所以乘上 (n−1)。初值 [00]=0。
# 第二类斯特林数
{mn} 表示把 n 个不同的数划分为 k 个不计顺序的非空子集的方案数。
递推式:
{kn}={k−1n−1}+k×{kn−1}
第 n 个数单独在一个集合,或者 n 合并到之前的集合中,有 k 个集合。初值 {00}=1
第二类斯特林数较为常用,且有如下公式:
mn=k=0∑min(n,m){kn}(km)k!
证明:
考虑组合意义:
{mn}=m!1k=0∑m(−1)k(km)(m−k)n
证明:
聪明伶俐的你一定发现了上面两个式子是符合二项式反演的!
简单推一下,先把第二个式子左右两边同乘 m!,并把等号右边的枚举空集合个数改成枚举非空集合,有:
{mn}m!=k=0∑m(−1)m−k(m−km)kn
设 gk=kn,fk={kn}k!,容易看出:
gm=k=0∑m(km)fkfm=k=0∑m(−1)m−k(km)gk
正好就是二项式反演的式子。
# 例题
# P6620 [省选联考 2020 A 卷] 组合数问题
题目要求计算:
(k=0∑nf(k)×xk×(kn))modp
但是一个多项式在里面显然很不好计算,考虑把多项式变成单项式,即:
k=0∑ni=0∑mai×ki×xk×(kn)
换一下求和顺序:
i=0∑maik=0∑nki×xk×(kn)
这样一来,第二个求和号后面的部分就变成了单项式求求和。
考虑通过上面讲的公式把 ki 拆开,即:
k=0∑n(j=0∑i{ji}(jk)j!)×xk×(kn)
根据组合恒等式,(kn)(jk)=(jn)(k−jn−j),有:
k=0∑nj=0∑i{ji}(jn)j!×xk×(k−jn−j)
再次交换求和顺序:
j=0∑i{ji}(jn)j!k=0∑n(k−jn−j)xk
考虑二项式定理的一般情况,(x+1)n=i=0∑n(in)xi
令 t=k−j,有:
j=0∑i{ji}njt=0∑n−j(tn−j)xt+jj=0∑i{ji}njt=0∑n−j(tn−j)xt×xjj=0∑i{ji}nj(1+x)n−jxj
完整的式子:
i=0∑maij=0∑i{ji}nj(1+x)n−jxj
不想预处理的话 O(m2logn) 也是可以过的。
# 斯特林数与阶乘幂
首先对于上升幂和下降幂有一种转换:
xn=(−1)n(−x)nxn=(−1)n(−x)n
把上升下降幂展开模拟一下可以得到。
对于第一类斯特林数:
xn=k=0∑n[kn]xk
证明… 懒得写了(众所周知,OI 不需要证明)
对于第二类斯特林数:
nm=k=0∑m{km}(kn)k!=k=0∑m{km}nk
# 斯特林反演
与二项式反演类似:
gn=k=0∑n{kn}fk⇔fn=k=0∑n(−1)n−k[kn]gk
证明不重要
# 例题
# [2018 雅礼集训 1-16] 方阵 (TopCoder-13444 CountTables)
题目描述
给出一个 n×m 大小的矩形,每个位置可以填上 [1,c] 中的任意一个数,要求填好后任意两行互不等价且任意两列互不等价,两行或两列等价当且仅当对应位置完全相同,求方案数 。
n,m≤5000
题解
首先不考虑列的限制,如果只有每行互不等价的方案数为 gm=(cm)n。
设如果有 m 列,且行列均互不等价的方案数为 fm。
那么有:
gm=i=0∑m{im}fi
枚举等价的列的组数为 i,把 m 列划分到 i 组中,再乘上这 n 行 i 组列互不等价的方案数 fi,即为 gm。
然后就先计算出 gk,再套斯特林反演计算 fm 即可。
# [BZOJ4671] 异或图
题目要求最终的图为一个连通图。
所以我们枚举有多少个联通块,设 fk 为恰好 k 个联通块时的方案数,gk 为至少 k 个联通快时的方案数,有:
gk=i=k∑n{ki}fi
把 i 个联通块划分到 k 个联通块中,再乘上 fi。
根据斯特林反演得:
fk=i=k∑n(−1)i−k[ki]gi
所以
f1=i=1∑n(−1)i−1[1i]gif1=i=1∑n(−1)i−1(i−1)!gi
现在难点就在于如何计算 gi 了,考虑枚举子集划分。连接两个集合的边亦或值必须是 0,子集内的边不用管。
然后对于每一个划分,用线性基找出边集的极大线性无关组,记为 tot,方案数就是 2m−tot。
# Catalan 数
# 定义
C0=C1=1
递推式:
Cn=i=1∑nCi−1Cn−i
通项公式:
Cn=(n2n)n+11=(n2n)−(n+12n)
生成函数(OGF):
H(x)=2x1−1−4x
证明:
H(x)=====n≥0∑Hnxn1+n≥1∑Hnxn1+n≥1∑i=0∑n−1HixiHn−i−1xn−i−1x1+xi≥0∑Hixin≥0∑Hnxn1+xH2(x)
解方程得:
H(x)=2x1±1−4x
当取正号时,令 x 趋近于 0,计算出 H0 为正无穷,而不是 1(不收敛),舍弃。所以应取负号。
# 组合意义
括号序列数(前缀 (
个数不小于 )
个数)。
进栈序列为 1,2,3⋯n 的出栈序列数。
将正 n+2 边形进行三角剖分方案数。
n 个节点的不同二叉树个数。
从 (0,0) 走到 (n,n),且不能经过直线 y=x+1 的方案数。
首先所有路径个数为 (n2n),减去不合法的,即经过 y=x+1 的路径。
把第一次经过 y=x+1 的点及之后的点全都与 y=x+1 进行对称,最后的终点必定在 (n−1,n+1) 上。
路径数为 (n+12n),减去就行了。
# 杂题选讲
# P2523 [HAOI2011]Problem c
记一下后缀确定位置个数和 si,如果 si>n−i+1 那么无解。
考虑 dp,设 fi,j 表示剩余 n−m 人中,编号 ≥i 的人,已经确定了 j 个人的方案数。
转移方程:
fi,j=k=0∑j(kj)fi+1,j−k
即枚举在第 i 个位置确定 k 个人,从 j 里选 k 个,乘上 fi+1,j−k。
答案为 f1,n−m。
# P4456 [CQOI2018] 交错序列
考虑对贡献进行转化:
xayb===(n−y)aybi=0∑a(ia)ni(−y)a−iybi=0∑a(−1)a−i(ia)niya+b−i
此时我们只需要计算 1 的个数即可,考虑如何维护 yx。
设 fi,j,0/1 表示考虑了前 i 位,最后一位为 0/1,合法的序列 1 的个数的 j 次方和。
转移方程:
结尾为 0:
fi,j,0=fi−1,j,0+fi−1,j,1
第 i 位是 0,不影响 1 的个数,且前面一位填 0 或 1 均可。
结尾为 1:
多了一个 1,贡献从 yj→(y+1)j,即 k=0∑j(kj)yk。
所以有转移方程:
fi,j,1=k=0∑j(kj)fi−1,k,0
因为最后一位为 1,前面一位只能填 0.
发现转移和 i 无关,对 i 进行矩阵快速幂。
f 数组长成这样:
[f0,0,f1,0,f2,0⋯fa+b,0,f0,1,f1,1⋯fa+b,1]
转移矩阵分成 4 个部分:
左上角:单位矩阵
左下角:单位矩阵
右上角:二项式系数,不过要横过来
右下角:全是 0
(自己推一下应该不难验证是对的)
最后枚举一下计算答案即可。
# CF1188C Array Beauty
首先对 a 从小到大排序,不影响答案。答案上界为 k−1an−a1。
考虑枚举美丽值 v,然后计算美丽值为 v 的子序列个数。
设 fi,j 表示美丽值大于等于 v 的情况下,前 i 个数选了 j 个的方案数。
转移方程:
fi,j=ai−ak≥v∑fk,j−1
不难发现 k 是单调不降的,维护一个指针即可。
时间复杂度 O(nkkV),即 O(nV)。
需要注意的是,我们 dp 出来的值是美丽值大于等于枚举的 v 的方案数,所以有两种写法:
(now,lst 分别为美丽值大于等于 v 的方案数和美丽值大于等于 v+1 的方案数)
# AT2370 [AGC013D] Piling Up
我们记录白球的个数为 x,那么黑球个数为 n−x。
操作可以分为 4 种情况:
先取白球,加入一白一黑,再取白球。
先取白球,加入一白一黑,再取黑球。
先取黑球,加入一白一黑,再取白球。
先取黑球,加入一白一黑,再取黑球。
4 种情况对白球个数的影响分别为 −1,0,0,+1。
设 fi,j 表示进行了 i 次操作,当前有 j 个白球的方案数。初值,f0,i=1.
转移方程:
若 j≥1:
fi+1,j−1+=fi,jfi+1,j+=fi,j
若 j<n:
fi+1,j+=fi,jfi+1,j+1+=fi,j
但是实际上这样是有问题的,初始时白球个数不同,相同的操作序列我们也会计算多次。
如何才能不重复计数呢?
考虑一个操作序列每次操作之后白球个数形成的折线。初始时白球个数不同只会导致这条折线上下平移。对于每条折线我们只算一次就行了。
不难发现,我们只计算碰到 x 轴的折线个数即可。
所以还要开个 dp 数组记录碰到 x 轴的方案数。
设 fi,j(i,j 含义同上面)表示碰到 x 轴的方案数,gi,j 表示没有碰到的方案数。
转移的时候判一下给谁转移就行。
# AT2062 [AGC005D] ~K Perm Counting
直接计算不是很好算,考虑容斥。
设 f(m) 表示排列中至少有 m 个 ∣pi−i∣=k 的方案数。
Ans=i=0∑n(−1)ifi
借用一下 @ez_lcw 的图:
这是 n=5,k=1 时的图,左边为点,右边为权值。
连边则表示 ∣pi−i∣=k。此时我们要选出一些边,且任意两条边不能在同一个点上。
把这些点平铺:
此时要使 ∣pi−i∣=k,那么必须是相邻两个点连边。
设 dpi,j,0/1 表示考虑了前 i 个点,连了 j 条边,第 i−1 个点和第 i 个点之间是否连边。
转移方程:
dpi,j,0=dpi−1,j,0+dpi−1,j,1dpi,j,1=dpi−1,j−1,0
需要注意一点,上图中 a5 和 1 之间不能连边,所以转移时也要特判一下。
我们已经有了 dp 数组之后,fm=dp2n,m×(n−m)!,然后计算答案即可。
# P4345 [SHOI2015] 超能粒子炮・改
答案为:
f(n,k)=i=0∑k(in)modP
然后就是一波愉快的推式子:
f(n,k)==i=0∑k(in)modPi=0∑k(i/Pn/P)(i%Pn%P)
根据 i/P 可以把式子分成几段:
=(0n/P)i=0∑P−1(in%P)+(1n/P)i=0∑P−1(in%P)+⋯+(k/Pn/P)i=0∑k%P(in%P)
除了最后一项前面的都可以合并起来:
f(n,k)==i=0∑P−1(in%P)j=0∑P/k−1(jn/P)+(k/Pn/P)i=0∑k%P(in%P)f(n%P,P−1)×f(n/P,P/k−1)+(k/Pn/P)f(n%P,k%P)
预处理到 f(P,P),组合数直接 Lucas,递归求解即可。
时间复杂度 O(P2+Tlogp2n)。
# 群论
# 置换
定义
有限集合到自身的双射(即一一对应)称为置换。集合 S={a1,a2,⋯,an} 的置换可以表示为:
f=(a1,a2,⋯,anap1,ap2,⋯,apn)
p1,p2,⋯,pn 为一个 1∼n 的排列,显然置换个数为 n!。
置换的乘法
置换的乘法是置换的叠加,如对于置换 f=(a1,a2,⋯,anap1,ap2,⋯,apn) 和 g=(ap1,ap2,⋯,apnaq1,aq2,⋯,aqn),置换的乘积 f∘g 为:
f∘g=(a1,a2,⋯,anaq1,aq2,⋯,aqn)
# 置换群
集合 S 的所有置换构成一个群,这个群的任意子群称为置换群。
置换群中的元素是置换。
# 轨道 - 稳定化子定理
(这个定理是为了证明 Burnside’s 引理,所以不看也没关系 /kk)
设 G 为置换群,X 为一种操作所有方案的集合(看不懂的话下面有例子)。
对于 ∀x∈X,G(x)={f(x)∣f∈G} 称为 x 的轨道,Gx={f∣f(x)=x,f∈G} 称为 x 的稳定化子。
轨道 - 稳定化子定理: ∣G(x)∣∣Gx∣=∣G∣
(对于置换 f,满足 f(x)=x 的元素称为该置换的不动点。)
# Burnside 引理
设 G 是集合 X 上的置换群,c(f) 为置换 f 的不动点个数,若 G 把集合 X 分为了 L 个等价类,则有:
L=∣G∣1f∈G∑c(f)
证明:
若集合中一个元素 x 的轨道大小为 ∣G(x)∣,那么有 ∣G(x)∣ 个元素的轨道都相同,每个元素的贡献为 G(x)1。
L===x∈X∑∣G(x)∣1∣G∣1x∈X∑∣Gx∣∣G∣1f∈G∑c(f)
例子:
一个 4 个点的环,染黑白两种颜色,循环同构,求本质不同方案数。
集合 X:不考虑重复的染色方案,共有 24 种。
不动点:旋转之后四个点的颜色与旋转之前一样,这样的染色方案叫做不动点。
置换群:置换群大小为 4,有 f0,f1,f2,f3 4 种置换,fi 表示旋转 i 次。
L:即为本质不同染色方案数。
L====∣G∣1f∈G∑c(f)∣G∣1(c(f0)+c(f1)+c(f2)+c(f3))41(16+2+4+2)6
# Pólya 定理
Poˊlya 定理提供了在特殊情况下计算不动点个数的方法。
考虑一种置换会形成许多置换环。
设 h(f) 为置换 f 的置换环数量,若要用 k 种颜色给集合 X 染色,那么有 c(f)=kh(f)。
证明:
因为要计算不动点个数,所以一个置换环上面的点颜色必须都一样,有 k 种选择。又由于一共有 h(f) 个置换环,所以方案数为 kh(f)。
进一步得:
L=∣G∣1f∈G∑kh(f)
# 例题
# P4980 【模板】Pólya 定理
Poˊlya 定理板题。
考虑如何计算置换环个数。
枚举旋转 k 个,即从 1 旋转到 k+1,那么循环节长度为 klcm(n,k),所以共有 lcm(n,k)/kn=gcd(n,k) 个循环节。
Ans=n1k=1∑nngcd(n,k)
然后就要用到莫反基本功了。
Ans===n1k=1∑nngcd(n,k)n1d∣n∑ndk=1∑dn[gcd(k,dn)=1]n1d∣n∑ndφ(dn)
暴力计算 φ 也可以通过。
# [POJ 1286] Necklace of Beads
题目描述
n 个珠子串成一个圆,用 3 种颜色去涂色。问一共有多少种不同的涂色方法。(旋转和对称同构)
题解
旋转同构和对称同构分开考虑。
置换群 G 的大小为 2n,所以把上面所有情况都加起来之后再除以 2n 就是答案。