各种容斥和反演乱做:Shuttle race I must be the chosen one
普通容斥
补集转化、子集容斥、数论容斥和莫比乌斯反演。
CF296B Yaroslav and Two Strings
考虑求出总方案数,然后扣掉:
- 不存在 \(s_i<w_i\) 的。
- 不存在 \(s_j>w_j\) 的。
- 同时两者都不存在的。
这个可以随便算,然后完了。
CF559C Gerald and Giant Chess
经典钦定容斥型 dp,但我又不会做了。考虑用一个组合数随便算出不考虑黑色块的抵达方案数,然后扣掉要经过黑色块的。
我们去考虑经过黑色块的路径怎么计数。可以钦定其在第一个黑色块处被数到,然后后面就可以随便走了。所以考虑 \(dp_i\) 表示不经过任何黑色块抵达第 \(i\) 个黑色块的方案数,转移时类似,先算出不考虑黑色块的方案数,然后扣掉要经过其他块的,从左上往右下转移即可。
最后可以把 \((h,w)\) 看成一个黑色块就能得到答案。
P6583 回首过去
StayAlone 无法爆杀题。其实不太难,自己花了个把小时就做出来了。放一下我写在代码里面的思考过程。
我们首先知道,对于分数 \(\frac{x}{y}\),在 \((x,y)=1\) 的情况下,\(y\) 只要不含有任何 \(2,5\) 以外的质因子,就是可以被有限位小数表示出来的。我们自然而然有一个想法,就是枚举此时的 \(y\),因为 \(2,5\) 质因子的含量都是 \(\log\) 级别的。
枚举 \(y\) 之后我们考虑怎么数。我们钦定一个分数 \(\frac{x}{y}\) 如果满足条件就会在它的最简形式被计数。考虑一个 naive 的办法:这样的话我们完全可以枚举与 \(y\) 互质的 \(x\),然后直接计算每个 \(\frac{x}{y}\) 能上下同时翻多少倍都数进去。因为质因子只有两个,我们自然想到先全部放进去,再抠掉 \((x,y)=2\) 和 \((x,y)=5\) 的部分。
为了方便处理,我们很容易想到去掉不好弄的 \(\gcd\):只要因数有 \(2\) 就抠掉,有 \(5\) 就抠掉,如果有 \(10\) 再补回去的操作方式。
需要注意并不是所有 \(y\) 都同时含有 \(2,5\)。
直接暴力枚举 \(x\) 可以获得 \(40\) 分。可以发现循环内是两个下取整除法取 \(\min\) 的格式,并且其中一个是定值(\(\frac{n}{y}\)),所以我们考虑用一个乱改过的整除分块(具体来说就是只有含某个因数的能对和做贡献,还要垒一个前缀和)来算,这样就做完了。
注意写法,写丑了就会被卡空间。
P4515 [COCI2009-2010#6] XOR
一个比较显然的容斥。我们考虑枚举所有子集,然后计算该子集中所有三角形的交集,把它乘上容斥系数放入贡献,就像算所有三角形的交一样。
手搓几个例子会好理解很多,而且可以发现对于子集 \(S\) 的容斥系数是 \((-2)^{|S|-1}\),非常好观察法。
P2231 [HNOI2002] 跳蚤
看出来了是要求 \(\gcd(a_i,M)=1\) 的方案数,但是我不会约数容斥。
考虑补集转化,我们求一下所有数 \(\gcd\geq 2\) 的数量有多少。这样很自然想到考虑枚举 \(M\) 的因子 \(x\),然后考虑所有数的方案数。明显当 \(a_i\) 都是 \(x\) 的因数的时候,方案数为 \((\left\lfloor\frac{M}{x}\right\rfloor)^{N}\),然后显然会算重。
考虑容斥,注意到 \(\gcd=3\) 的方案数和 \(\gcd=2\) 的方案数会统计重 \(\gcd=6\) 的方案数,我们希望它只数一次,所以我们得给它减掉。这里的容斥系数没有那么显而易见,因为可以注意到对于 \(\gcd=12\) 这样的方案会在 \(\gcd=2\) 处算一次,\(\gcd=3\) 处算一次,\(\gcd=4\) 处扣一次于是干脆不用记了……经过一些结论推导可以得知容斥系数为 \(\mu(x)\)。
不是,你都上 \(\mu\) 了还不莫反啊?
不急,先来一个比较傻的东西。
值域约数容斥和莫比乌斯反演
值域约数容斥
考虑写一个东西 $g(n)=\sum\limits_{d|n} f(d)$,然后我们移项一下:$f(n)=g(n)-\sum\limits_{d|n\land d\neq n} f(d)$。我们通常使得 $f$ 为相等型的函数(某某与 $x$ 相等的有 $f(x)$ 个),$g$ 为整除型的函数(满足某某整除 $x$ 的有 $g(x)$ 个),然后做一些事情。显然 $g$ 通常比 $f$ 更好算,尤其是在 $\gcd$ 问题当中。这个东西的一个变体是 \(g(n)=\sum\limits_{d=1} f(dn)\),然后我们移项使得 \(f(n)=g(n)-\sum\limits_{d>1} f(dn)\)。
这样做之后复杂度通常可以做到调和级数,\(\mathcal O(n\ln n)\)。
例题:CF1884D Counting Rhyme。勿忘国耻。
那这个题能不能用这个做到一个虽然过不了的复杂度?
令 \(f(n)\) 表示所有数的 \(\gcd=n\) 的方案数,\(g(n)\) 表示所有数的 \(\gcd\) 满足 \(n|\gcd\) 的方案数。显然有 \(g(n)=\left\lfloor\frac{M}{n}\right\rfloor^{N}\)。
于是直接用记忆化做一遍就行了。复杂度过不了但是可以拿大把部分分。写了一个果然是对的:Submission。
考虑莫比乌斯反演。
我们知道 \(\mu(d)=\begin{cases}1,& n=1\\0,& p^2|n\land p\ \text{is a prime}\\(-1)^k,& n\ \text{includes}\ k\ \text{different primes}\end{cases}\)。
线性筛求积性函数
我知道你肯定不会线性筛。欧拉筛的工作原理就是让一个数在最小质因子处被筛掉。
枚举 \(i\in[1,n]\),没被标记过的 \(i\) 就是质数,但是不管它是不是质数,看一遍前面已经有的所有质数 \(pr\)。观察 \(i\times pr\) 的性质。显然先要标记它不是质数。
如果 \(i\not\equiv 0\pmod pr\),那就说明 \(pr\) 是 \(i\times pr\) 一个新的质因子,并且肯定是最小质因子,因为如果不是,它会在更早的时候被标记到。所以 \(pr\) 就是最小质因子。我们把这种叫情况 \(1\)。
然后考虑 \(pr|i\) 的时候,这个时候对于更大的数而言 \(i\) 里面就会包含一个更小的质因子,所以不满足条件了,break 出去。我们把这种叫情况 \(2\)。
写法记住就行了,我蠢蠢的。然后我们综合一下以上内容,我们知道:对于一个最小质因子 \(pr\) 出现了恰好一次的数 \(x\),它会在 \(\frac{x}{pr}\) 枚举质数 \(pr\) 时的情况 \(1\) 处被筛到;对于一个最小质因子 \(pr\) 出现了数次的数 \(x\),它会在 \(\frac{x}{pr}\) 处枚举质数 \(pr\) 时被枚举到,并且这个数枚举完就 break 了。
这样可以帮助我们筛积性函数。对于情况 \(1\),转移 \(f(x)\gets f(\frac{x}{pr})\times f(pr)\) 即可,因为互质;对于情况 \(2\),考虑已经有 \(pr\) 的 \(\frac{x}{pr}\) 再多一个最小质因子 \(pr\) 的贡献就可以了,这通常是容易的。
我们显然可以用这个来筛 \(\mu\)。
整除分块
我们想数 $\sum\limits_{i=1}^n \left\lfloor\frac{n}{i}\right\rfloor$,考虑把相同的塞在一段数。枚举 $l$,则根据经典结论,$r=\left\lfloor\frac{n}{\left\lfloor\frac{n}{l}\right\rfloor}\right\rfloor$,$[l,r]$ 的贡献都是相同的。使用一个循环即可做原问题:初始设置 $l=1$,计算 $r$,累贡献,要算下一个直接在循环中进行 $l\gets r+1$,直到 $l>n$。复杂度为 \(\mathcal O(\sqrt n)\)。
使用于各种积性函数筛。
Dirichlet 卷积
$(f*g)(n)=\sum\limits_{d|n} f(d)g(\frac{n}{d})$,则 $f*g$ 为 $f,g$ 的狄利克雷卷积。一个很重要的事实也是莫反的基本原理:$\mu*1=\varepsilon$,其中 $1$ 是常函数,$\varepsilon=[n=1]$。由 \(\mu*1=\varepsilon\),\([n=1]=\sum\limits_{d|n}\mu(d)\)。
这个有什么好处呢?用亚线性的复杂度检查是不是 1,你把 \(n\) 换成 \(\gcd(i,j)\) 就得到了莫反的式子:
显然我们常常能够枚举 \(d\),然后做一些有用的事情。
我们考虑不沿用那个补集转化,直接莫反求 \(\gcd(M,a_i)=1\) 的方案数。这里把 \(a_i\) 可以看成是一个整体,也可以看成是表示 \(a\) 的 \(\gcd\)。于是考虑:
后面这坨东西是会做的。也就是要求序列的 \(\gcd\) 是某个数倍数的方案数,显然是 \(\left\lfloor\frac{M}{d}\right\rfloor^{N}\)。
于是最后要做的就是:
如果空间够的话,线性筛一遍 \(\mu\) 即可。这题空间不够,但可以记忆化搜索。
二项式反演
考虑这三个东西:
- 容斥原理:我们令 \(F(x)\) 表示钦定某 \(x\) 个位置然后至少这 \(x\) 个位置不满足条件的方案数,则恰好所有位置均满足条件(\(0\) 个位置不满足条件)的方案数为 \(\sum\limits_{i=0} (-1)^iF(i)\)。
你很容易发现容斥原理的弊端:我们总是只能计算全部位置都满足条件或者全部位置都不满足条件的方案数。
- 补集转化:我们令 \(F(x)\) 表示至少有 \(x\) 个位置不满足条件的方案数,则恰好 \(m\) 个位置不满足条件的方案数为 \(F(m)-F(m+1)\)。
你很容易发现补集转化的弊端:我们需要保证一个有超过 \(x\) 个位置不满足条件的方案只能被恰好计数一次。这样的要求比较强悍,通常是不容易计数的。
- 二项式反演:我们令 \(F(x)\) 表示钦定某 \(x\) 个位置然后至少这 \(x\) 个位置不满足条件的方案数,再设恰好 \(m\) 个位置不满足条件的方案数 \(G(m)\)。我们首先有 \(F(m)=\sum\limits_{i=m}^n {i\choose m} G(i)\)。然后我们使用二项式反演把 \(G\) 反演出来。
可以发现二项式反演没有什么劣处。
二项式反演有两个常用的形式。一个是 \(G(i)\) 会被每个子集的 \(F\) 计算到一次的,一个是 \(G(i)\) 会被每个超集的 \(F\) 计算到一次的。
- \(F(n)=\sum\limits_{i=0}^n {n\choose i}G(i)\iff G(n)=\sum\limits_{i=0}^n(-1)^{n-i}{n\choose i}F(i)\)。
- \(F(m)=\sum\limits_{i=m}^n {i\choose m}G(i)\iff G(m)=\sum\limits_{i=m}^n(-1)^{i-m}{i\choose m}F(i)\)。这个是最常用的,因为可以看成是令 \(F(x)\) 表示钦定某 \(x\) 个位置然后至少这 \(x\) 个位置不满足条件的方案数,\(G\) 表示恰好的方案数。
第二个式子在 \(m=0\) 时退化为容斥原理。
P1595 信封问题
求 \(D_n\) 表示 \(\{p_n\}\) 的错排数。
可以发现,我们可以钦定 \(i\) 个位置按照一种 \(D_i\) 错开,剩下的位置维持原来不变。显然这样我们一定可以生成所有排列:
直接应用二项式反演,\(D_n=\sum\limits_{i=0}^n(-1)^{n-i}{n\choose i}i!\)。预处理阶乘和阶乘逆元即可做到 \(\mathcal O(n)\)。
[ABC309G] Ban Permutation
看到 \(\forall\) 一眼容斥。我们不妨钦定至少 \(i\) 个位置满足 \(|P_i-i|\ge x\),但是我们发现这个不好数,因为需要存的信息太多了,不存那么多又会有后效性。所以我们不妨先补集转化一下,改成钦定至少 \(i\) 个位置 \(|P_i-i|<x\),那么剩下的 \(n-i\) 个位置就可以直接在剩下 \(n-i\) 个空位里面任取了。
dp 做就可以了,显然需要状压一下前后 \(X\) 位。
这个题的另一个做法(顺便可以解决 2nd Qingbai Cup T2)
排列有一个美妙的转化:我们转成二分图完美匹配。左部点表示位置,右部点表示值,这样显然任意一个排列都一一对应一个二分图 \(G([1,n],[1',n'])\) 的完美匹配。
然后考虑一对 \((i,j')\),我们进行一波交换,把小的那个钦定到左部点里面去,显然这是不影响的。这样的好处有两个!
- 绝对值转成了右部点减左部点。
- 我们只需要知道其中一个部点的和,就能知道另一个部点的和,就能知道所有匹配的差的和。
然后自然地,由于我们把每个匹配都钦定成小的那个在左部了,我们对所有点按照值从小到大枚举:\(1,1,2,2,3,3\cdots n,n\)。那么一个点只有两种可能:成为一个新的左部点,或者成为一个新的右部点和一个前面未匹配的左部点匹配掉。
再设计 dp 是容易的了。我们只需要存下最近 \(X\) 的 \(2X\) 个点的匹配状态,就能在每次向右移动值的时候知道往差为 \(X\) 之外有多少种匹配。状态和转移都比较显然。
CF285E Positions in Permutations
为 了 一 碟 醋 包 了 一 盘 饺 子
看到恰好 \(m\) 条件反射启动二项式反演。不妨钦定至少 \(i\) 个位置满足 \(|P_i-i|=1\),这个和上面 ABC 那个题是一个套路,存一下最近这 \(3\) 位就可以了。
似乎这种排列值减下标差值的题的套路都是状压下来呢……
子集反演
类似二项式反演,我们设置 \(F(S)\) 和 \(G(S)\),分别表示包含(是超集)和恰好。于是首先有 \(F(S)=\sum\limits_{T\subseteq S} G(T)\)。
式子也类似二项式反演。子集反演告诉我们,\(G(S)=\sum\limits_{T\subseteq S} (-1)^{|S|-|T|}F(T)\)。
类似地,在 \(F(S)\) 表示至少(是子集)的时候也存在子集反演:
证明与二项式反演类似,需要使用容斥。川子在青岛集训的时候应该讲过,例题是小星星。
min-max 容斥
咕咕咕。
斯特林数
第二类斯特林数
\(\begin{Bmatrix}n\\ k\end{Bmatrix}\),或者 \(S(n,k)\),是第二类斯特林数。它描述将 \(n\) 个有标号物品放入 \(k\) 个无标号非空集合的方案数。
递推式是较为简单的。我们有:
第一种情况对应新物品自成一个集合,第二种情况对应新物品放入一个已经存在的集合。
我们考虑它的通项公式。
容易发现,将 \(n\) 个物品放入 \(k\) 个有标号可空集合的方案数为 \(F(k)=k^n\)。那么考虑将 \(n\) 个物品放入 \(k\) 个有标号不可空集合的方案数 \(G(k)\),容易发现它和 \(F(k)\) 构成类似二项式反演的关系:
也就是选择一些集合是空集。
使用二项式反演我们容易有 \(G(k)=\sum\limits_{i=0}^k(-1)^{k-i}{k\choose i}F(i)\)。注意从有标号转到无标号需要除以一个 \(k!\)。于是展开可以得到第二类斯特林数的通项公式:
显然,对于 \(\forall k\in [0,n]\),我们只需卷一下就好了。

浙公网安备 33010602011771号