快速沃尔什变换与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的主要内容,如果未能解决你的问题,请参考以下文章

FWT快速沃尔什变换学习笔记

浅谈快速沃尔什变换

HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)

模板快速沃尔什变换

Codeforces 662C(快速沃尔什变换 FWT)

FWT(快速沃尔什变换)