高维前缀和/SOSDP/FWT/FMT 小结
首先,著名口胡家 C 提出重要论断,这四个东西是一个东西。
考虑问题的原本形态:
- 目前你有一个定义域为 \([0, 2^n)\) 的函数 \(f(S)\),令另一函数 \(g(S) = \sum_{T \subseteq S} f(T)\),在 \(O(n2^n)\) 的复杂度下求解出 \(g(S)\)。
显然可以根据子集和形态利用二项式定理暴力枚举子集做到 \(O(3^n)\),但是因为其特殊结构我们可以使用逐维前缀和的方式求解得到 \(O(n2^n)\) 的复杂度,具体代码如下:
for (int i = 0; i < n; ++i) {
// Loop over i-th dimension.
for (int st = 0; st < (1 << n); ++st) {
// This condition implies that i-th dimension is 1.
if ((st >> i) & 1) {
// ps[... 1 ...] += ps[... 0 ...]. (i-th dimension)
ps[st] += ps[st ^ (1 << i)];
}
}
}
这样相当于对于每一位分别做前缀和,可以证明这样不重不漏是对的。
将 \(g(S)\) 看成一个 DP 数组,那么我们也可以称这个结构为 SOSDP。
下面解释一下为什么 FMT 也等价于这个结构(其实是使用这个结构处理 FMT 的问题),FMT 要解决的问题如下:
- 求 \(f(S) = \sum_{P \oplus Q = S} g(P)h(Q)\),其中在这里 \(\oplus\) 可以为 or, and。
考虑子集反演,得到 \(f'(S) = \sum_{P | Q \subseteq S} g(P)h(Q)\),使用子集反演可以得到 \(f(S) = \sum_{T \subseteq S}(-1)^{|S| - |T|} f'(T)\),现在仅需将 \(f'(S)\) 求出即可求得 \(f(S)\),那么显然有:
\[f'(S) = \sum_{P \subseteq S, Q \subseteq S} g(P)h(Q) \to f'(S) = (\sum_{P \subseteq S} g(P))(\sum_{Q \subseteq S} h(Q))
\]
那么对于两个东西都做一遍上述结构即可,考虑 and 的情况就是将子集变成了超集。
其中 FWT 是将符号更改为 xor,同样可以推得系数,但是有点复杂,也可以使用上述做法实现。

浙公网安备 33010602011771号