Loading [MathJax]/jax/element/mml/optable/GeneralPunctuation.js

快速沃尔什变换与k进制FWT

这是一篇用来卖萌的文章QAQ


考虑以下三类卷积

Ck=iorj=kAiBj

Ck=iandj=kAiBj

Ck=ixorj=kAiBj

由于前两种可以用FMT(高维前缀和)解决,那我们就谈谈第三种吧

下文中的n都是形如2i1的数

下标的开与闭是根据好不好写来定的,但是还是可以意会的...


虽然有人知道为什么了,但是我还是不知道为什么要这么做

我们尝试寻找一个矩阵T,其(i,j)元为w(i,j),使得

TATB=TC

我们不妨记TA=fwt(A)

自然的,fwt(A)[x]=ni=0w(x,i)Ai

那么,等式两边同时展开,我们可以得到

fwt(A)[x]fwt(B)[x]=fwt(C)[x]

ni=0w(x,i)Ainj=0w(x,j)Bj=nk=0w(x,k)Ck

对比两边Ck的表达式, 我们自然希望这个变换满足

ij=kAiBjw(x,i)w(x,j)=Ckw(x,k)

如果有w(x,i)w(x,j)=w(x,k)(ij=k),那么我们就能得到ij=kAiBj=Ck

这不就是我们想要的式子嘛....,

那我就构造一个满足w(x,i)w(x,j)=w(x,k)(ij=k)T矩阵


不仅如此,我们还需要可以快速地计算出fwt(A)

fwt(A)[i]=nk=0w(i,k)Ak=n/2k=0w(i,k)w(i,0)Ak+nk=n/2w(i,k)w(i,n/2)

不难注意到,前半部分已经成为了一个子问题,然而后半部分还没有

我们希望通过w的某些性质,能够使得右边成为一个子问题

联想到w需要满足异或的性质,因此,我们不妨让w拥有可以按位拆分的性质

w(i,j)=...k=0w(i&2k,j&2k)

下面的化式子来源于rqy神仙

如果有上面的性质,我们记i的二进制的最高位为i1,其他位为i0k同理

那么,原本的式子可以转化成

fwt(A)[i]=n/2k=0w(i1,0)w(i0,k0)Ak+nk=n/2w(i1,1)w(i0,k0)Ak=w(i1,0)fwt(A0)[i0]+w(i1,1)fwt(A1)[i0]

应该看得出A0A1是什么吧...

复杂度为T(n)=2T(n/2)+O(n)=O(nlogn)


那么,考虑构造w,其实只要构造一个22的矩阵,由于C需要逆变换,因此矩阵还要有逆

[w(0,0)w(0,1)w(1,0)w(1,1)]

根据上面的异或性质,我们有

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

然后就可以弄出这么一个矩阵

[1111]=[0.50.50.50.5]1

然后代进程序即可


k进制FWT


计算Ck=ij=kAiBj

由于K进制下,FMT仍然能解决或卷积以及和卷积,因此FWT一般用来解决异或卷积

在下文中,n=Ki1

自然地,还是希望构造TATB=TC

还是一样的展开

fwt(A)[x]fwt(B)[x]=fwt(C)[x]

ni=0w(x,i)Ainj=0w(x,j)Bj=nk=0w(x,k)Ck

还是一样的对比系数,然后我们能够得出,当w(x,i)w(x,j)=w(x,k)(ij=k)时,这样子做的正确性有保证

并且,同样的,不妨设i=(i0i1i2...im)k

那么,我们构造w(i,j)=mt=0w(it,jt)


我们根据ik进制下的最高位来讨论,我们记一个数xk进制下的最高位为x,其余位为x

\begin{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)nK的幂)


我们需要考虑K * KT矩阵是什么

由于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},那么我们取出来的实际上就是范德蒙德矩阵!

\begin{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} \begin{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的提示

posted @   remoon  阅读(1838)  评论(0编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
点击右上角即可分享
微信分享提示