数学杂记
子集反演 and 高维前缀和
第一个式子也是高维前缀和,具体实现:
void work(){
FOR(i,0,(1<<n)-1)b[i]=a[i];
FOR(i,0,n-1)
FOR(S,0,(1<<n)-1)
if(S>>i&1)
b[S]+=b[S^(1<<i)];
}
时间复杂度是 \(\mathcal{O}(n2^n)\)。这个实际上是分别对每一维进行了前缀和,或者说是前 \(i\) 维,是个 dp 的形式,具体来说就是在转移的时候,\(b_S\) 中含有 \(i\) 这一维,而 \(b_{S\oplus(1<<i)}\) 还处于上一维。
相应地还有高维后缀和以及对应的另一种形式的子集反演,也就是枚举超集:
顺带一提高维差分只需要把倒序循环,并且改成减法即可。
好了来看一道例题:
e.g.1
给定 \(k\) 个质数 \(p_1,\cdots,p_k\) 和正整数 \(n\),求 \(n\) 以内不被 \(p_1,\cdots,p_k\) 中任何数整除的数的个数。
正难则反。设 \(a_S\) 为恰好被在 \(S\) 中的数整除的数的个数,注意不允许被集合之外的数整除,再设 \(b_S\) 为能被 \(S\) 中的数整除的数的个数,这里不要求恰好了。于是我们所求的就是 \(a_0\)。
不难发现:
又从定义可知:
那么直接运用子集反演的超集形式就做完了:
e.g.2 P1450 [HAOI2008] 硬币购物
设 \(a_S\) 表示只有 \(S\) 中的元素使用了多于 \(d_i\) 次,再设 \(b_S\) 表示钦定 \(S\) 中的元素使用了多于 \(d_i\) 次。于是就很显然了,\(b_S=\sum_{S\subseteq T}a_T\),一个子集反演就搞定了。
考虑怎么求 \(b\)。如果我们先让 \(S\) 中的数使用 \(d_i+1\) 次,剩下的就是个完全背包。
通过这道题也能看出来,这实际上就是个简单容斥原理,毕竟只有四个数。但是容斥原理是否没那么形式化?而子集反演可以准确的给出表达式。所以说子集反演是容斥原理的严格化描述。不过也可能是我对容斥完全不理解导致的。
e.g.3
填一个长度为 \(m\) 的数列,其中每位的取值是 \([1,k]\)。问 \([1,k]\) 每个数都出现了的方案数。\(k\le 10^6\)。
设 \(a_S\) 表示正好出现了 \(S\) 中的数的方案数,\(b_S\) 有 \(S\) 中的数出现了,但不一定全出现。最终答案是 \(a_{1\cdots k}\)。
依然可以套路地做:
但是问题就在于这个东西过不去啊,\(k\) 很大。而后观察到这个式子的特殊之处:\(b_S\) 只与 \(S\) 的大小有关,我们并不关心它具体是什么。那么可以改为枚举 \(T\) 的大小。
这样只需要 \(\mathcal{O}(k)\) 的时间复杂度了。
哪里来的二项式系数啊?哦哦哦原来是——
二项式反演
要区分这里的“至多,至少”和前缀和/后缀和对应的“至多至少”,二项式反演的“至多,至少”实际上是钦点一部分满足条件,其余部分随意,而前缀和/后缀和的“至多,至少”是钦点一部分满足条件之后,其他的必须不满足,所以前者是带一个二项式系数的。
—— do_while_true
常用的有两种形式:
形式一(至多和恰好的转换):
形式二(至少和恰好的转换):
注意 \(g_i\) 是恰好的,也就是答案。
于是我们可以直接秒掉 e.g.3 了:
e.g.3 EX
直接设 \(g_i\) 为恰好出现 \(i\) 个的方案数,\(f_i\) 为至多出现 \(i\) 个的方案数,\(f_i=i^m\),然后直接二项式反演就行了:
发现和上面是一致的。
e.g.4
求 \(1\) 到 \(n\) 的排列 \(p_{1\cdots n}\) 的数量,使得 \(\forall 1\le k\le n,p_k\neq k\)。
设 \(g_i\) 为恰好有 \(i\) 个 \(p_i=i\) 的排列数量,\(f_i\) 为至少有 \(i\) 个 \(p_i=i\) 的数量。易知 \(f_i=\binom{n}{i}(n-i)!\),然后二项式反演:
e.g.5
求 \(1\) 到 \(n\) 的排列 \(p_{1\cdots n}\) 的数量,使得 \(\forall 1\le k< n,p_{k+1}\neq p_k+1\)。
同理设 \(f_i,g_i\) 分别表示至少和恰好。
考察 \(f_i\) 的组合意义。先选出 \(i\) 个满足 \(p_{k+1}=p_k+1\),并把每个等式连边。于是就得到了 \(n-i\) 条链。注意每条链内部顺序是固定的,所以 \(f_i=\binom{n-1}{i}(n-i)!\),然后二项式反演就行了。
插板法
这个就比较简单了但是我每次都记不住...
\(\sum_{i=1}^mx_i=n\) 的方案个数:
如果 \(x_i>0\) 那么就是 \(\binom{n-1}{m-1}\),如果 \(x_i\ge 0\) 就是 \(\binom{n+m-1}{m-1}=\binom{n+m-1}{n}\)。
还有更强的,但是暂时没见过。
references:

浙公网安备 33010602011771号