给定数列 $ a_{0\dots 2^{k}-1} $ 求 $ b $ 满足 $ b_{s} = \sum_{i\in s} a_i $
实现方法很简单,
for( i in 0 to n-1 )
for( j in 0 to 2^n-1)
if( j & ( 1 << i ) )
a[j] += a[j ^ ( 1 << i )]
然后称为 $ B = \text{FMT}(A) $ ,快速莫比乌斯变换
想要还原也很简单,把代码反着写:
for( i in n-1 downTo 0 )
for( j in 2^n - 1 downTo 0)
if( j & ( 1 << i ) )
a[j] -= a[j ^ ( 1 << i )]
当然, $ i $ 的顺序可以是原来的顺序,因为按照哪个顺序枚举位根本不重要
同时,$ j $ 的顺序也不重要,考虑对于一个数字,它只有在当前枚举的位数为 1 的时候才被执行,所以就算已经枚举到这位是 0 的状态,它也不会被更新。
这样 $ A = \text{IFMT}( B ) $
FMT 可以写成 FFT 那样的形式,就不赘述了。
或卷积就需要用到这个东西。
或卷积是指:
\[
C_s = \sum_{i|j=s} A_i B_j
\]
有一个结论, $ \text{FMT}(C) = \text{FMT}(A) \cdot \text{FMT}(B) $ ,其中 \(\cdot\) 指点积,也就是把每个位置的函数值乘起来。
原因是 $ (i \cup j) \sube s $ 等价于 $ (i \sube s) and (j \sube s) $ 。于是
\[
\begin{aligned} \ [x]FMT(C) &=\sum_{s \sube x}C_s\\&= \sum_{s \sube x}\sum_{i|j = s}A_iB_j\\&= \sum_{i|j \sube x} A_iB_j\\&= ( \sum_{i\sube x} A_i )(\sum_{j\sube x} B_j)\\&= [x]FMT(A) \cdot [x]FMT(B) \end{aligned}
\]
所以有 $ \text{FMT}(C) = \text{FMT}(A) \cdot \text{FMT}(B) ) $
于是可以 $ O(n2^n) $ 做这个。
子集卷积长这样:
\[
C_s = A\times_{subset} B = \sum_{i|j=s,i\&j = 0} A_i B_j
\]
如果设 $ p(x) $ 为 $ x $ 的 popcount( 1 的个数),那么:
\[
(i|j = s) , (i\&j = 0) \Leftrightarrow i|j = s , p(i)+p(j) = p(s)\\C_s = \sum_{i|j = s , p(i)+p(j) = p(s)} A_iB_j
\]
我们把 $ C $ 扩展到二维,设 $ C‘{x,k} $,定义如下:
\[
C'_{x,s} = \sum_{i|j = s,p(i)+p(j) = x} A_iB_j[p(s) = x]
\]
把 $ C $ 扩展到二维了,$ A $ 也扩展到二维,定义 $ A‘{p,s} $
\[
A'_{x,s} = \left\{\begin{aligned}&0 & {p(s) \neq x}\\&A_{s} & {p(s) = x} \end{aligned}\right.
\]
同理定义 $ b‘_{x,s} $
我们知道
\[
C'_{x,s} = \sum_{i|j = s,p(i)+p(j) = x} A'_{p(i),i} B'_{p(j),j}
\]
观察到 \(C'_x = \sum_{i=0}^x A'_{i}\times_{or} B'_{x-i}\) ,而且需要最后去掉左边的 $ p(s) \neq x $ 的情况。
这样复杂度 $ O(n^3 2^n) $,一共要卷 $ n^2 $ 次。
注意 $ \text{FMT} , \text{IFMT} $ 都有可加性,所以我们把那个或卷积写成 $ \text{FMT} $ 的形式
\[
\begin{aligned}C'_{x} &= \sum_i IFMT(FMT(B'_i) · FMT(B'_{x-i}))\\&= IFMT( \sum_i FMT(A_i') · FMT(B_{x-i}') )\end{aligned}
\]
我们现在只需要处理出所有 $ A‘_i $ 和 $ B‘_i $ 的卷积,最后再跑 $ n $ 次逆 FMT ,所以这样做就优化到了 $ O( 2^n n^2 ) $
原文:https://www.cnblogs.com/yijan/p/12387352.html