快速沃尔什变换与k进制FWT
Posted reverymoon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速沃尔什变换与k进制FWT相关的知识,希望对你有一定的参考价值。
这是一篇用来卖萌的文章QAQ
考虑以下三类卷积
(C_k = sum limits_{i ;or;j = k} A_i * B_j)
(C_k = sum limits_{i;and;j = k} A_i * B_j)
(C_k = sum limits_{i;xor;j = k}A_i * B_j)
由于前两种可以用FMT(高维前缀和)解决,那我们就谈谈第三种吧
下文中的(n)都是形如(2^i - 1)的数
下标的开与闭是根据好不好写来定的,但是还是可以意会的...
虽然有人知道为什么了,但是我还是不知道为什么要这么做
我们尝试寻找一个矩阵(T),其((i, j))元为(w(i, j)),使得
[TA cdot TB = TC]
我们不妨记(TA = fwt(A))
自然的,(fwt(A)[x] = sum limits_{i = 0}^n w(x, i) * A_i)
那么,等式两边同时展开,我们可以得到
[fwt(A)[x] cdot fwt(B)[x] = fwt(C)[x]]
[sum limits_{i = 0}^n w(x, i) * A_i sum limits_{j = 0}^n w(x, j) * B_j = sum limits_{k = 0}^n w(x, k) * C_k]
对比两边(C_k)的表达式, 我们自然希望这个变换满足
[sum limits_{i oplus j = k} A_i * B_j * w(x, i) * w(x, j) = C_k * w(x, k)]
如果有(w(x, i) * w(x, j) = w(x, k) ;(i oplus j = k)),那么我们就能得到(sum limits_{i oplus j = k} A_i * B_j = C_k)
这不就是我们想要的式子嘛....,
那我就构造一个满足(w(x, i) * w(x, j) = w(x, k) ;(i oplus j = k))的(T)矩阵
不仅如此,我们还需要可以快速地计算出(fwt(A))
[
egin{aligned}
fwt(A)[i] &= sum limits_{k = 0}^n w(i, k) A_k &= sum limits_{k = 0}^{n / 2} w(i, k) w(i, 0) A_k + sum limits_{k = n / 2}^n w(i, k) w(i, n / 2)\end{aligned}
]
不难注意到,前半部分已经成为了一个子问题,然而后半部分还没有
我们希望通过(w)的某些性质,能够使得右边成为一个子问题
联想到(w)需要满足异或的性质,因此,我们不妨让(w)拥有可以按位拆分的性质
[w(i, j) = prod_{k = 0}^{...} w(i;&;2^k, j ;&;2^k)]
下面的化式子来源于rqy神仙
如果有上面的性质,我们记(i)的二进制的最高位为(i_1),其他位为(i_0),(k)同理
那么,原本的式子可以转化成
[ egin{aligned} fwt(A)[i] &= sum limits_{k = 0}^{n / 2} w(i_1, 0) w(i_0, k_0) A_k + sum limits_{k = n / 2}^n w(i_1, 1) w(i_0, k_0) A_k &= w(i_1, 0) fwt(A_0)[i_0] + w(i_1, 1) fwt(A_1)[i_0]\end{aligned} ]
应该看得出(A_0)和(A_1)是什么吧...
复杂度为(T(n) = 2T(n / 2) + O(n) = O(n log n))
那么,考虑构造(w),其实只要构造一个(2 * 2)的矩阵,由于(C)需要逆变换,因此矩阵还要有逆
[ egin{bmatrix} w(0, 0) & w(0,1)\ w(1,0)& w(1,1) end{bmatrix} ]
根据上面的异或性质,我们有
[ w(0, 0) * w(0, 0) = w(0, 0) ;;;;...(1)w(0, 1) * w(0, 0) = w(0, 1) ;;;;...(2)w(0, 1) * w(0, 1) = w(0, 1) ;;;;...(3)w(1, 0) * w(1, 1) = w(1, 1) ;;;;...(4)w(1, 1) * w(1, 1) = w(1, 0);;;; ...(5)w(1, 0) * w(1, 0) = w(1, 0) ;;;;... (6) ]
注意到矩阵要有逆,因此秩需要为(2)
然后就可以弄出这么一个矩阵
[
egin{bmatrix} 1& 1\ 1& -1 end{bmatrix} = egin{bmatrix}
0.5& 0.5 .5& -0.5\end{bmatrix}^{-1}
]
然后代进程序即可
(k)进制(FWT)
计算(C_k = sum limits_{i oplus j = k} A_i * B_j)
由于(K)进制下,FMT仍然能解决或卷积以及和卷积,因此FWT一般用来解决异或卷积
在下文中,(n = K^i - 1)
自然地,还是希望构造(TA cdot TB = TC)
还是一样的展开
[fwt(A)[x] cdot fwt(B)[x] = fwt(C)[x]]
[sum limits_{i = 0}^n w(x, i) * A_i sum limits_{j = 0}^n w(x, j) * B_j = sum limits_{k = 0}^n w(x, k) * C_k]
还是一样的对比系数,然后我们能够得出,当(w(x, i) * w(x, j) = w(x, k) ;(i oplus j = k))时,这样子做的正确性有保证
并且,同样的,不妨设(i = (i_0 i_1 i_2 ... i_m)_k)
那么,我们构造[w(i, j) = prod limits_{t = 0}^{m} w(i_t, j_t)]
我们根据(i)在(k)进制下的最高位来讨论,我们记一个数(x)在(k)进制下的最高位为(x'),其余位为(x'')
[ egin{aligned} fwt(A)[i] &= sum limits_{t = 0}^n w(i, t) A_t &= sum limits_{t = 0}^{k - 1} w(i', t) sum limits_{x' = t} w(i'', x'') A_x &= sum limits_{t = 0}^{k - 1} w(i', t) fwt(A_t)[i''] end{aligned} ]
复杂度是(T(n) = kT(n / K) + O(Kn) = O(nK log_K n))((n)是(K)的幂)
我们需要考虑(K * K)的(T)矩阵是什么
由于(w(x, i) * w(x, j) = w(x, k) (i oplus j = k)),也就是(w(x, i) * w(x, j) = w(x, k) ([K | i + j - k]))
注意到单位根在复平面意义下有循环的意义
因此,我们尝试取(w(x, i) = w_k^{xi}),那么我们取出来的实际上就是范德蒙德矩阵!
[ egin{bmatrix} 1& 1 & 1& ... & 1\ 1& w_k^1& w_k^2& ... & w_k^{k - 1}\ 1& w_k^2 & w_k^4& ... & w_k^{2(k - 1)}\ ...& ...& ...& ...& ...\ 1& w_k^{k - 1}& w_k^{2(k - 1)} & ... & w_k^{(k - 1)(k - 1)} end{bmatrix} ]
由于范德蒙德卷积的行列式为(prod limits_{i < j} (x_i - x_j)),在这个单位根矩阵中,不存在两两相等的数
因此这个有逆,事实上, 在FFT中,我们早已经见过这个矩阵的逆矩阵了,它是
[ frac{1}{k} egin{bmatrix} 1& 1 & 1& ... & 1\ 1& w_k^{-1}& w_k^{-2}& ... & w_k^{-(k - 1)}\ 1& w_k^{-2} & w_k^{-4}& ... & w_k^{-2(k - 1)}\ ...& ...& ...& ...& ...\ 1& w_k^{-(k - 1)}& w_k^{-2(k - 1)} & ... & w_k^{-(k - 1)(k - 1)} end{bmatrix} ]
原因是([n | t] = sum limits_{i = 0}^{n - 1} w_n^{ti})
这样,我们就可以成功的计算出k进制FWT啦!
感谢rqy和dkw的提示
以上是关于快速沃尔什变换与k进制FWT的主要内容,如果未能解决你的问题,请参考以下文章