数学杂记

子集反演 and 高维前缀和

\[\begin{aligned} b_S&=\sum_{T\subseteq S}a_T\\ \Longrightarrow a_S&=\sum_{T\subseteq S}(-1)^{|S|-|T|}b_T \end{aligned} \]

第一个式子也是高维前缀和,具体实现:

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)}\) 还处于上一维。

相应地还有高维后缀和以及对应的另一种形式的子集反演,也就是枚举超集:

\[\begin{aligned} b_S&=\sum_{S\subseteq T}a_T\\ \Longrightarrow a_S&=\sum_{S\subseteq T}(-1)^{|T|-|S|}b_T \end{aligned} \]

顺带一提高维差分只需要把倒序循环,并且改成减法即可。

好了来看一道例题:

e.g.1

给定 \(k\) 个质数 \(p_1,\cdots,p_k\) 和正整数 \(n\),求 \(n\) 以内不被 \(p_1,\cdots,p_k\) 中任何数整除的数的个数。

正难则反。设 \(a_S\) 为恰好被在 \(S\) 中的数整除的数的个数,注意不允许被集合之外的数整除,再设 \(b_S\) 为能被 \(S\) 中的数整除的数的个数,这里不要求恰好了。于是我们所求的就是 \(a_0\)。

不难发现:

\[b_S=\sum_{S\subseteq T}a_T \]

又从定义可知:

\[b_S=\left\lfloor\frac{n}{\prod_{i\in S}p_i}\right\rfloor \]

那么直接运用子集反演的超集形式就做完了:

\[a_0=\sum_T(-1)^{|T|}\left\lfloor\frac{n}{\prod_{i\in T}p_i}\right\rfloor \]

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}\)。

依然可以套路地做:

\[\begin{aligned} b_S&=\sum_{T\subseteq S}a_T\\ &=|S|^m\\ a_{1\cdots k}&=\sum_{T}(-1)^{k-|T|}|T|^m \end{aligned} \]

但是问题就在于这个东西过不去啊,\(k\) 很大。而后观察到这个式子的特殊之处:\(b_S\) 只与 \(S\) 的大小有关,我们并不关心它具体是什么。那么可以改为枚举 \(T\) 的大小。

\[a_{1\cdots k}=\sum\limits_{i=0}^k(-1)^{k-i}\binom{k}{i}i^m \]

这样只需要 \(\mathcal{O}(k)\) 的时间复杂度了。

哪里来的二项式系数啊?哦哦哦原来是——

二项式反演

要区分这里的“至多,至少”和前缀和/后缀和对应的“至多至少”,二项式反演的“至多,至少”实际上是钦点一部分满足条件,其余部分随意,而前缀和/后缀和的“至多,至少”是钦点一部分满足条件之后,其他的必须不满足,所以前者是带一个二项式系数的。
—— do_while_true

常用的有两种形式:

形式一(至多和恰好的转换):

\[f_i=\sum_{j=0}^i\binom{i}{j}g_j\Longleftrightarrow g_i=\sum_{j=0}^i\binom{i}{j}(-1)^{i-j}f_j \]

形式二(至少和恰好的转换):

\[f_i=\sum_{j=i}^n\binom{j}{i}g_j\Longleftrightarrow g_i=\sum_{j=i}^n\binom{j}{i}(-1)^{j-i}f_j \]

注意 \(g_i\) 是恰好的,也就是答案。

于是我们可以直接秒掉 e.g.3 了:

e.g.3 EX

直接设 \(g_i\) 为恰好出现 \(i\) 个的方案数,\(f_i\) 为至多出现 \(i\) 个的方案数,\(f_i=i^m\),然后直接二项式反演就行了:

\[g_k=\sum_{i=0}^k\binom{k}{i}(-1)^{k-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)!\),然后二项式反演:

\[g_0=\sum_{i=0}^n\binom{i}{0}(-1)^i\binom{n}{i}(n-i)!=\sum_{i=0}^n(-1)^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:

posted @ 2024-07-25 14:56  LHLeisus  阅读(10)  评论(0)    收藏  举报