FWT
快速沃尔什变化
很骚
\(
\begin{aligned}
\\\\
\end{aligned}
\)
先考虑这样一个问题
现有 \(F(x)\,G(x)\) 两个数组, \(S(x)=\sum_{i|j=x}F(i)*G(j)\) ,求 \(S(i)\) 的每个值
为了方便,令 \(n=2^m\)
我也不知道咋想到的,两边同时加一个 \(\sum\) 得
\( \begin{aligned} \sum_{k \subseteq x}S(k)&=\sum_{k \subseteq x}\sum_{i|j=k}F(i)*G(j)\\ &=\sum_{i \subseteq x}F(i) * \sum_{j \subseteq x}G(j) \end{aligned} \)
(所有 \(x\) 的子集都可以表示为两个 \(x\) 的子集的或)
这左右三坨东西长得都很像,如果我们用 \(F'(x)\) 表示 \(\sum_{i \subseteq x}G(i)\) 可得
\(S'(x)=F'(x)*G'(x)\)
然后我们会发现 \(F'(x)\,G'(x)\) 并不难求,只需要用一个 *高维前缀和* 即可求出
*高维前缀和* :可以把每个二进制位看成一维,每一维有 \(0,1\) 两个坐标,一共m个维度,每次选定其中一维,让每个在当前维度坐标为 \(1\) 的点 加上当前维度坐标为 \(0\) 的,其他维坐标不变的点 的值。可通过二维和三维前缀和辅助理解。
这玩意是 \(O(nlogn)\) 的
我们就可以做到 \(O(nlogn)\) 求出 \(F'(x)\,G'(x)\) ,再以 \(O(n)\) 求出 \(S'(x)\) ;至于 \(S(x)\) ,我们做一遍高位前缀和的逆变换就行了,即高维差分
成功解决,时间复杂度 \(O(nlogn)\)
\(
\begin{aligned}
\\
\end{aligned}
\)
再来考虑另一个类似的问题
现有 \(F(x)\,G(x)\) 两个数组, \(S(x)=\sum_{i\&j=x}F(i)*G(j)\) ,求 \(S(i)\) 的每个值
你可以 \(F(x)\,G(x)\) 反过来,按照上一题的求出 \(S(x)\) 反过来,再反一次就能得到 \(S(x)\) ,但这不优雅,常数也不太优秀。
我们考虑也像上一道题一样,两边加 \(\sum\)
\(
\begin{aligned}
\sum_{k \supseteq x}S(k)&=\sum_{k \supseteq x}\sum_{i\&j=k}F(i)*G(j)\\
&=\sum_{i \supseteq x}F(i) * \sum_{j \supseteq x}G(j)
\end{aligned}
\)
(所有 \(x\) 的超集都可以表示为两个 \(x\) 的超集的与)
然后高位后缀和一下,让 每个在当前位为 \(0\) 的点 加上当前位为 \(1\) 的点,其他位不变的 的值。
成功解决,时间复杂度 \(O(nlogn)\)
\(
\begin{aligned}
\\\\
\end{aligned}
\)
再来考虑另一个不太类似的问题
现有 \(F(x)\,G(x)\) 两个数组, \(S(x)=\sum_{i \land j=x}F(i)*G(j)\) ,求 \(S(i)\) 的每个值
发现好像不太好加 \(\sum\) 了。
我们考虑上面两个问题做法的本质,以第一个为例:对于每个二进制位的 \(\{x_0,x_1\}\) ,我们将它变换成了 \(\{x_0,x_0+x_1\}\) ,而且每一位是独立的;并且变换后的 \(F'(x),G'(x)\) 可以直接相乘求得 \(S'(x)\)
然后…………我也不知道怎么想到的,可以得到一个变换:对于每个二进制位的 \(\{x_0,x_1\}\) ,我们将它变换成 \(\{x_0+x_1,x_0-x_1\}\) , 这样变换后的 \(F'(x)\) 实际是 \(\sum_{popcount(i \& x)\text{为偶数}}F(x)-\sum_{popcount(i \& x)\text{为奇数}}F(x)\) ,
\( \begin{aligned} F'(x)*G'(x)&=(\sum_{popcount(i \& x)\text{为偶数}}F(i)-\sum_{popcount(i \& x)\text{为奇数}}F(i))*(\sum_{popcount(i \& x)\text{为偶数}}G(i)-\sum_{popcount(i \& x)\text{为奇数}}G(i))\\ &=\sum_{popcount(i \& x)\text{为偶数}}\sum_{j\land k=i}F(j)*G(k)-\sum_{popcount(i \& x)\text{为奇数}}\sum_{j\land k=i}F(j)*G(k)\\ &=S'(x) \end{aligned} \)