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

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


考虑以下三类卷积

Ck=iorj=kAiBjCk=iorj=kAiBj

Ck=iandj=kAiBjCk=iandj=kAiBj

Ck=ixorj=kAiBjCk=ixorj=kAiBj

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

下文中的nn都是形如2i12i1的数

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


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

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

TATB=TCTATB=TC

我们不妨记TA=fwt(A)TA=fwt(A)

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

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

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

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

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

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

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

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

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


不仅如此,我们还需要可以快速地计算出fwt(A)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

fwt(A)[i]=nt=0w(i,t)At=k1t=0w(i,t)x=tw(i,x)Ax=k1t=0w(i,t)fwt(At)[i]

复杂度是T(n)=kT(n/K)+O(Kn)=O(nKlogKn)nK的幂)


我们需要考虑KKT矩阵是什么

由于w(x,i)w(x,j)=w(x,k)(ij=k),也就是w(x,i)w(x,j)=w(x,k)([K|i+jk])

注意到单位根在复平面意义下有循环的意义

因此,我们尝试取w(x,i)=wxik,那么我们取出来的实际上就是范德蒙德矩阵!

[111...11w1kw2k...wk1k1w2kw4k...w2(k1)k...............1wk1kw2(k1)k...w(k1)(k1)k]

由于范德蒙德卷积的行列式为i<j(xixj),在这个单位根矩阵中,不存在两两相等的数

因此这个有逆,事实上, 在FFT中,我们早已经见过这个矩阵的逆矩阵了,它是

1k[111...11w1kw2k...w(k1)k1w2kw4k...w2(k1)k...............1w(k1)kw2(k1)k...w(k1)(k1)k]

原因是[n|t]=n1i=0wtin

这样,我们就可以成功的计算出k进制FWT啦!


感谢rqy和dkw的提示

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