FMT 与 FWT

【预备知识】

子集反演公式:

f(S)=TSg(T)g(S)=TS(1)|S||T|f(T)

f(S)=STg(T)g(S)=ST(1)|S||T|f(T)

如果用 g 直接暴力算 f,复杂度是 O(3n) 的;使用 SOSDP 则可以把复杂度优化至 O(n2n),具体不再赘述。

f 子集反演算 g 也可以 SOSDP,同样 O(n2n) 求)

【FMT】

FMT,快速莫比乌斯变换。它解决这么一个问题:

给定两个序列 a0a2n1b0b2n1,求序列 c0c2n1,满足:将下标 I 看作 n 大小的子集,cI=JK=IaJbK

这种问题叫或卷积。

N=2n,首先容易发现有一个 O(N2) 的解法,即枚举 J,K 累加答案。

FMT 可以用来解决这类问题,复杂度为 O(NlogN)=O(2nn),和 SOSDP 一样。

下面介绍一下 FMT。


在开始之前,我们先回顾一下 FFT 是怎么做普通卷积的。

  1. a,b 分别做 DFT。

  2. 求出 c 的 DFT。

  3. 做 iDFT 求出 c

这个做法的关键在于:存在一个变换 DFT,使得 DFT 和 iDFT 做起来都很快,而且 DFT(ab)=DFT(a)DFT(b)


然后回到原问题。我们记 aba,b 的或卷积。

为了解决问题,我们希望找到变换 t 满足:t 和 it 都很快,且 t(ab)=t(a)t(b)

一个很牛的事实是,这种变换确实存在,它们叫做 DMT 和 iDMT。即莫比乌斯变换和逆莫比乌斯变换。

介绍一下,DMT(a)=(a0,,aN),其中 aI=JIaJ。即把 a 变换为它的前缀和。显然做这个变换和逆变换可用 SOSDP 在 O(n2n) 做,问题只剩下一个性质。


引理:c=ab,则 c=ab

证明:

cX=IXcI=IXJK=IaJbK=JXKXaJbK=(JXaJ)(KXbK)=aXbX

因此可以 O(n2n)a,b 的高维前缀和,乘起来之后再用子集反演 O(n2n) 求出 c

另外,FMT 还可以做与卷积:把 aI=JIaJ 换做 aI=IJaJ 即可。证明过程也类似,方向换一下即可。

【FWT】

FWT,快速沃尔什变换,用于解决异或卷积问题。问题定义类似。

同样地,我们要找一个变换 t,同样满足上面的性质。

而一样很牛的事实是,这样的变换也存在,叫做 DWT 和 iDWT。

DWT(a)=a0^,,aN^,其中 a^I 的定义不再是前后缀和:a^I=J(1)|IJ|aJ

看起来相当奇怪。

先说明 DWT 和 iDWT 都可以 O(n2n) 计算。

引理iDWT(a)=DWT(a)/2n

引理证明

转证 DWT(DWT(a))=a2n,这和引理是等价的。

为什么呢?

b=DWT(a),由原本引理有 DWT(b)=a2nDWT(b)/2n=aDWT(b/2n)=ab/2n=iDWT(a),能这么做的原因是 DWT 其实是线性变换,所以 DWT(x)/C=DWT(x/C)

接下来证明转化命题。不妨设 b=DWT(a),c=DWT(b),求证 cI=aI2n

cI=J(1)|IJ|bJ=J(1)|IJ|K(1)|JK|aK=KaKJ(1)|IJ|(1)|JK|=KaKJ(1)|IJ||JK|=KaKJ(1)|(IK)J|

观察上式,(IK)J 有什么规律?当 IK=\empty 时,J 无论怎么取,系数都是 1,因此 J(1)=2n;而 IK\empty 时,系数会正负抵消,总共的贡献为 0

因此,J(1)|(IK)J|=2n,得证。


算法:只考虑怎么 DWT。

fa 的前 2n1 项的 2n220 位的结果,g 为后 2n1 项的 2n220 位的结果。注意是只考虑更低位。

有结论:DWT(a)=(DWT(f)+DWT(g),DWT(f)DWT(g)),即前一半项是求和,后一半项是做差。

如果有这个结论,很显然就可以分治 O(NlogN)=O(n2n) 来做。其实这和 FFT 非常相似,区别只在于 DFT 是按照奇偶分治下去,DWT 直接按下标分治。

问题只在于结论证明。


求证0I<2n1aI^=fI^+gI^a^I+2n1=f^Ig^I

证明

a^I(I<2n1)=0J<2n(1)|IJ|aJ=0J<2n1(1)|IJ|aJ+2n1J<2n(1)|IJ|aJ=f^I+2n1J<2n(1)|IJ|aJ=f^I+0J<2n1(1)|I(J+2n1)|aJ+2n1=f^I+0J<2n1(1)|I(J+2n1)|aJ+2n1=f^I+0J<2n1(1)|IJ|aJ+2n1 (注意 I 的范围)=f^I+g^I

a^I+2n1(I<2n1)=0J<2n(1)|(I+2n1)J|aJ=0J<2n1(1)|(I+2n1)J|aJ+2n1J<2n(1)|(I+2n1)J|aJ=0J<2n1(1)|IJ|aJ+0J<2n1(1)|(I+2n1)(J+2n1)|aJ=f^I+0J<2n1(1)|IJ|+1aJ=f^Ig^I

证毕。


然后说明 DWT(ab)=DWT(a)DWT(b)

证明:

引理(1)|IJ|=(1)|I|(1)|J|

比较显然,因为异或后受到影响的只有同时在 I,J 中的元素,左边会让它们的影响变成 1,而右边在 I,J 中各算一个 1,乘起来还是 1

证明

cX^=I(1)|IX|JK=IaJbK=J,K(1)|X(JK)|aJbK=J,K(1)|(JX)(KX)|aJbK=J,K(1)|JX|aJ(1)|KX|bK=J(1)|JX|aJK(1)|KX|bK=aX^bX^

【深入理解】

可能会觉得 DMT, DWT 的式子比较生硬,于是我们深入理解一下这两个东西到底在干嘛。

DFT 是在做点值,DMT 和 DWT 其实也是在做另一种意义上的点值。

具体来说,我们需要用到集合幂级数

对于一个序列 a0aN,定义一个多元多项式 A(x1xn)=0I<2naIx1i1x2i2xnin,其中 i1inI 这个集合的二进制表示。

这个多项式有 2n 项,每一项的系数就是 a。这个 A 叫做集合幂级数。可以类比序列对应到 OGF 上。简记 A(x1xn)=0I<2naIx1i1x2i2xninA(x)=IaIxI


看看 DMT 是在干嘛。令 J=(j1,,jn){0,1}n,即一个集合。

注意到当 IJ,存在 it=1,jt=0,此时有 jtit=0,所以 j1i1jnin=0

IJ 时,(it,jt)=(0,0)/(0,1)/(1,1)jtit=1,所以 j1i1jnin=1

因此,A(J)=IJaI=aJ

所以 DMT 计算 a 实际上是求出了 A{0,1}n2n 个点处的值。


再看看 DWT 是在干嘛。令 J=(j1,,jn){0,1}n,即一个集合。

那么 P=((1)j1,(1)j2,,(1)jn){1,1}n

A(P)=0I<2naI(1)i1j1(1)i2j2(1)injn=0I<2naI(1)i1j1++injn=0I<2naI(1)IJ

:向量 a,b 的点乘 ab=aibi。上面 ij 实际上是把 i,j 两个集合看作了向量(或者说 01 串)进行运算。

ij 在某一位上取 1,当且仅当这一位上 i,j 都是 1,所以:

A(P)=0I<2naI(1)|IJ|=a^J

所以 DWT 实际上是求出了 A{1,1}n2n 个点处的值。

总之,FFT, FMT, FWT 都是在先点值后插值。

例题

经验:什么涉及位运算,什么就作为集合幂级数的指数。

例如要求一些东西的与等于 p,放到集合幂级数的指数上,定位乘法为与卷积后,答案就是 xp 的系数。

Nim (Topcoder 11469)

问有多少序列 (i1im) 满足:

  1. i1im=0

  2. 1ijk

  3. ij 为质数。

m109,k50000


构造一个序列 a0a65536,使 aI=11IK,IPrime

构造一个集合幂级数 A(x)=aIxI

在乘法定义为异或卷积(aIxIbJxJ=aIbJxIJ)时,Am(x)x0 的系数就是答案。

Am(x) 怎么算?

A(m)(x)=iDWT(DMT(A(m)(x))=iDMT((DMT(A(x))m)

因此只要做一次 DMT,然后让所得序列的每一项变成 m 次方,再做一次 iDMT 即可。注意这里是点乘 m 次不是卷积 m 次。

这题可以类比多项式快速幂:fm(x)=explnfm(x)=expmlnf(x)

CF449D

给定 a1an,计数 (1i1<<ikn),使 ai1andai2andandaik=0

n,ai106


考虑取 u=2201。定义集合幂级数 F(x)=(xai+xu)。这里 xaixu 都是集合幂级数,u 相当于全集。也就是说,令 A(x)=I[I=ai]xI,U(x)=U[I=U]xI,则 xai+xu=A(x)+U(x)

令乘法为与卷积,答案就是 F(x)x0 的系数。这也说明为什么取 u=2201,因为全集是与运算的单位元。

问题转化为求 [x0]F(x)。令 DMT 为与卷积的点值。

F(x)=iDMT(DMT(xa1+xu)DMT(xan+xu))。注意在做了 DMT 后的乘法是点乘。

注意到 xai+xu 每一项的系数只有在 ai,u 处才取 1,其余为 0

所以做 DMT 后,每一项系数为 1/2。当 Iai 时为 2,其余为 1。(aˇI=IJaJ

这有什么用呢?记 SˇI=((xai+xu))I,有 SˇI=2tI,其中 tI 表示 a1an 中包含 I 的个数。

那么问题转化为求 t0t2n1,即给定一些集合,求每个集合被多少个包含。这也是 SOSDP 能做的。如果要类比 DMT,令 cnt(J)a1anJ 的个数。则 tI=IJcnt(J),也是后缀和。

那么这一题就做完了,复杂度 O(20220)t0t2n1,然后 O(20220) 做一次 iDMT 得到 F(x),答案取 x0 系数。

posted @   FLY_lai  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示