FFT(快速傅里叶变换)、NTT(快速数论变换)

1.复数

1.1 复数的引入和定义

1.1.1 略谈数集扩充

略了很多字。

在数学在现实应用领域的发展过程中,我们常需要解类似的方程: x2+a=0 ,然而这在实数集下无解。

1.1.2 虚数单位于的引入与复数的定义

于是虚数单位 "i"被引入,并且有 i2=1

复数表示为实数与虚数的符合形式,如 a+bi a,bR ,让新集“复数集”表示为 C

定义复数相等:z1=a+bi,z2=c+diz1=z2a=c,b=d

表示为复数的四则运算加减乘除,则 (G,) 会是一个阿贝尔群。于是类似 x2+a=0 可以有复数解 ai2 。自然而然,复数集便可被扩充。

  1. 复数通常可以用代数形式表示:z=a+bi ,其中 az 的实部,读作 azreal part ,写作 Re(z)=abz 的虚部,读作 bzImaginary part ,写作 Im(z)=b

  2. 一种复数的常见形式为三角形式z=r(cosθ+isinθ) s.t. rRr 为复数的模 |z|θ 为辐角 Arg z(cosθ,sinθ) 为直角坐标。

  3. 另一种复数的常见形式为指数形式z=rexp(iθ)=reiθ=r(cosθ+isinθ) 。最后一步变换为欧拉公式: eix=cosx+isinx ,后文会提到。

1.1.3 虚数的引入

定义虚数集,它与实数集划分复数集。

在复数的代数形式 z=a+bi 下:

  1. b=0z 是实数。
  2. b0z 是虚数。
    • 特别的,若 b0a=0z纯虚数。纯虚数集真包含于虚数集。

1.2 复数的性质与四则运算

1.2.1 复数的几何意义

考虑一根无限长的一维的数轴,定义实数单位 1 为水平正方向,显然“所有实数”与数轴上的“坐标”形成双射。

选取一条无限长的数轴过 0 垂直于原数轴,定义虚数单位 i 为竖直正方向,得到一个二维空间。

对于复数的代数形式 z=a+bi ,显然“所有 (a,b)” 与二维空间的“平面直角坐标”形成双射。

对于复数的三角形式 z=r(cosθ+isinθ) ,显然“所有 r(cosθ,sinθ)” 与二维空间的“三角坐标”形成双射。

二维空间的点可以看作向量,比如复数 z 可以看作向量 OZ 。显然地,复数可以相等,但不能比较大小。

所有向量的起点移动到原点即得到一个坐标系。

1.2.2 复数的加法与减法

定义复数加法:z1=a+bi,z2=c+di 。则 z1+z2=(a+c)+(b+d)i

  1. 封闭性:z1,z2C ,则 z3=z1+z2C
    证明: z3=z1+z2=ac+bdi ,显然 z3 能表现为复数的代数形式,即 z3C
  2. 结合律:z1,z2,z3C ,则 (z1+z2)+z3=z1+(z2+z3)
    证明: (a+c)+(b+d)i+e+fi=a+bi+(c+e)+(d+f)i=(a+c+e)+(b+e+f)i
  3. 单位元: C 中有且仅有一个 e 满足 e+z=z+e=z ,则 eG 的单位元。
    证明: 显然有且仅有 e=0
  4. 逆元:aC ,都有且仅有一个 b 满足 a+b=b+a=e ,则 ba 的逆元。
    证明: 显然对于任意 a ,有且仅有 b=a
  5. 交换律:z1,z2C ,则 z1+z2=z2+z1
    证明: a+bi+c+di=c+di+a+bi=(a+c)+(b+d)i

1,2,3,4(C,+) 是个群。再由 5(C,+) 是个阿贝尔群。

减法是加法的逆运算,如 (z1+z2)z2=z1 。于是 (C,) 是个阿贝尔群。

1.2.3 复数的乘法与除法

定义复数乘法:z1=a+bi,z2=c+di ,则 z1z2=(a+bi)(c+di)=ac+adi+bci+bdi2=(acbd)+(ad+bc)i 。(显然复数乘法在几何意义上与向量点积和叉积无关。)

  1. 封闭性:z1,z2C ,则 z1z2C
    证明:z1=a+bi,z2=c+di,z3=z1z2 ,则 z3=z1z2=(a+bi)(c+di) ,继续展开得到 z3=ac+adi+bci+bdi2=(acbd)(ad+bc)i ,显然 z3 能表现成复数的代数形式,即 z3C
  2. 结合律:z1,z2,z3C ,则 (z1z2)z3=z1(z2z3)
    证明: ((a+bi)(c+di))(e+fi)=(a+bi)((c+di)(e+fi)) 是直观显然的。
  3. 单位元:C 中有且仅有一个 e 满足 ez=ze=z ,则 eG 的单位元。
    证明: 显然 C 中有且仅有 e=1
  4. 逆元:aC ,都有 ab=ba=e ,则 ba 的逆元。
    证明: 观察 (a+bi)(x+yi)=1 ,当且仅当 a+bi0 时有解。
  5. 交换律:z1,z2C ,则 z1z2C
    证明: (a+bi)(c+di)=(c+di)(a+bi) 是直观显然的。

1,2,3,4(C{0},×) 是个群。再由 5(C{0},×) 是个阿贝尔群。

除法是乘法的逆运算,于是 (C{0},/) 是个阿贝尔群。

1.2.4 辐角

1.2.4.1 复平面

在几何意义中已经对复数二维空间的方向进行过一个定义,实数单位 1 为水平正方向,虚数单位 i 为竖直正方向。

现在可以补充说明,将所有复数向量的起点移动到原点后,这个复数二维空间即复平面

1.2.4.2 辐角和辐角主值

一个复数 z=a+bi 可以表示出坐标 (a,b) 。定义 Arg zz辐角,有 tan(Arg z)=ba

定义 z辐角主值主辐角arg z ,有 π<arg zπ

需要注意,辐角不值某个角,而是指一个集合。 Arg z={arg z+2kπkZ}

1.2.4.3 单位圆
  1. 所有模小于等于 1 的复数在复平面上构成单位圆
  2. 模为 1 的复数为单位复数。所有单位复数构成构成单位圆周
1.2.4.4 极坐标

在极坐标的视角下表示复数坐标,则 (a,b)=(r,θ) 。其中 r=a2+b2,θ=Arg z

借助极坐标,复数乘法和除法的几何意义非常好理解。

  1. 乘法:z1z2=(r1r2,θ1+θ2) ,即模相乘,辐角相加。
  2. 除法:乘法的逆运算,z1/z2=(r1/r2,θ1θ2) ,即模相除,辐角相减。

1.2.5 共轭复数

共轭复数,即模相等,辐角相反的的两个复数(角相反:即角的绝对值相等,符号相反)。几何意义上关于实轴对称。z=a+bi 的共轭复数写作 z¯=abi

共轭复数是一种应用数学领域中常见的复数,具有以下性质。

  1. zz¯=|z|2
    代数证明: (a+bi)(abi)=a2abi+abib2i2=a2+b2=(a2+b2)2
    极坐标证明: (r,θ)(r,θ)=(r2,0)=r2
  2. z¯¯=z
    代数证明: a+((b))i=a+bi
    极坐标证明: (r,(θ))=(r,θ)
  3. z±w=z¯±w¯
    证明: z+w=(a+bi)+(c+di)=(a+c)+(b+d)i=(a+c)(b+d)iz¯+w¯=(abi)+(cdi)=(a+c)(b+d)i 。于是 z+w=z¯+w¯。减法是加法逆运算。
  4. zw=z¯w¯
    代数证明: z2=(a+bi)(c+di)=(acbd)+(ad+bc)i=(acbd)(ad+bc)iz¯w¯=(abi)(cdi)=(acbd)+(a(d)+(b)c)i=(acbd)(ad+bc)i 。于是 zw=z¯w¯ 。除法是乘法的逆运算。
    极坐标证明: zw=(r1r2,θ1+θ2)=(r1r2,(θ1+θ2))z¯w¯=(r1,θ1)(r2,θ2)=(r1r2,(θ1+θ2)) 。于是 zw=z¯w¯ 。除法是乘法的逆运算。

1.3 欧拉公式、复指数函数、复三角函数

1.3.1 欧拉公式

以欧拉命名的常见公式不止一个,这里指的是最出名的欧拉公式。
欧拉公式是欧拉创造的,被誉为“最美丽的数学公式”的公式,它将实数、虚数、三角函数联系到了一起,是一个数集的桥梁,在后世中应用广泛。
欧拉公式: eix=cosx+isinx
不严谨的说明:
已知泰勒展开为:
f(x)x=01i!xi
先确定三个函数的 Taylor 展开式,已知(首先很经典,其次课本上说的)它们的展开式是收敛的:
1. ex=i=0n1i!xi+o(xn)
2. cosx=i=0n(1)2i+21(2i)!x2i+o(x2n)
3. sinx=i=0n(1)2i1(2i+1)!x2i+1+o(x2n+1)

eix=x00!+ix11!x22!ix33!+x44!+ix55!x66!ix77!
cosx=x00!x22!+x44!x66!+
isinx=i11!ix33!+ix55!ix77!+
可以发现 cosx+isinx=1+i10!x22!ix33!+x44!+ix55!x66!ix77!+=eix

特殊的,有 eπi=1 这个恒等式较为常用。
证明: eπi=cosπ+isinπ=1+i×0=1

1.3.2 复指数函数

复指数函数在实数集上的定义与实指数函数的定义一致。
对于复数 z=x+iy ,定义函数 expz=ex+iy=ex(cosy+isiny)
复数函数在复平面上的性质:

  1. 模横正:|expz|>0
    证明: |expz|=|ex(cosy+isiny)|=ex>0
  2. 辐角主值:arg expz=y
    证明: exsinyexcosy=tany ,于是 arg expz=y
  3. 加法定理:exp(z1+z2)=exp(z1)exp(z2)
    代数证明:
    z1=a+bi,z2=c+di ,有

    exp(a+c+(b+d)i)=ea+c(cos(b+d)+isin(b+d))exp(a+bi)exp(c+di)=ea(cosb+isinb)ec(cosd+isind)=ea+c(cosbcosd+icosbsind+isinbcosd+i2sinbsind)=ea+c(cosbcosdsinbsind)+i(cosbsind+sinbcosd)=ea+c(cos(b+d)+isin(b+d))于是exp(z1+z2)=exp(z1)exp(z2)

    极坐标证明:

    expz1expz2=ea+b(cosb+isinb)(cosd+isind)=ea+b(1,b)(1,d)=ea+b(1,b+d)=ea+b(cos(c+d)+isin(c+d))=exp(z1+z2)

  4. 周期性:expz 是以 2πi基本周期周期函数
    证明: exp(z+2πi)=exp(z)exp(πi)exp(πi)=exp(z)

1.3.3 复三角函数

复三角函数在实数集上的定义与实三角函数的定义一致。
然而复三角函数在算法竞赛领域似乎未曾见过应用,暂时只给出复余弦函数复正弦函数的定义和几个常见性质。

  1. cosz=exp(iz)+exp(iz)2
    显然 exp(iz)+exp(iz)2=cosz+isinz+cos(z)+isin(z)2=cosz
  2. sinz=exp(iz)exp(iz)2i
    显然 exp(iz)exp(iz)2i=cosz+isinzcos(z)isin(z)2i=sinz
  3. 特殊的,若 zR ,则:
    1. cosz=Re(exp(iz))
    2. sinz=Im(exp(iz))
      显然 exp(iz)=cosz+isinz

复三角函数在复平面上的几个性质:

  1. 奇偶性:
    1. cosz 是复平面上的偶函数。
      证明: coszcos(z)=exp(iz)+exp(iz)2exp(iz)+exp(iz)2=0
    2. sinz 是复平面上的积函数。
      证明: sinz+sin(z)=exp(iz)exp(iz)2i+exp(iz)exp(iz)2i=0
  2. 周期性:coszsinz 在复平面上的基本周期为 2π
    证明: exp(w+2π)=exp(w)exp(2π)=exp(w)
  3. 值域:不同于实余弦函数与实正弦函数值域为 [1,1] ,复余弦函数与复正弦函数的值域为 C{0}
    证明:z=a+bi s.t.a,bR ,记 u=exp(b+ai)=eb(cosa+isina)C{0} 。显然 cosz=12(u+1u)C{0} 。显然 sinz=12i(u1u)C{0}
  4. 三角恒等式:实际上基本符合实三角恒等式,暂时只给出常见的 cos2z+sin2z=1 证明。
    证明: 有复数的几何意义与勾股定理则显然。

1.4 单位根

复数意义下的解叫做复根
xn=1 的解叫做 n单位复根n单位根

可以断言 n 次单位复根有且仅有 n 个,且是从 1 开始将等分单位元的 n 个复数。
证明: 由欧拉公式 e2πi=1 ,两边做 k 次幂有 e2kπi=1 ,再取 n 次根 1n=e21nkπi=cos21nkπ+isin21nkπ 。由于 2π 是一个周期,于是一个周期内的解集为 k={0,1,2,,n1}

wn0=wnn=1 ,逆时针依次为 wn0,wn1,wn2,,wnn1 。其中 wn1 通常直接被写作 wn

w1=1 是平凡的,不存在扩展性质。

n2 时具有性质:

  1. 互异性:0i<n,j s.t.ijwniwnj
    证明: 复数乘法,考虑极坐标系下, wnk=(1,k2πn)k={0,1,2,,n1} 互不相同。
  2. 加法定理:wna+b=wnawnb
    证明: 极坐标系下 wnk=(1,k2πn) 。于是 wna+b=(1,(a+b)2πn)=(1,a2πn)(1,b2πn)=wnawnb
  3. 可除公约数性: wlnlk=wnk
    证明: 设极坐标系下 wnk=(1,k2πn),wlnlk=(1,lk2πnl) 。显然 (1,lk2πnl=(1,k2πn))wnk=wlnlk
    特殊的,w2n2k=wnk ,又叫折半性
  4. 周期性:wnk+n=wnk
    证明: wnk+n=wnkwnn=wnk
  5. 对称性:w2nk+n=w2nk
    证明: 显然地 w2nn=1w2nk+n=w2nkw2nn=w2nk
  6. 一定性:k=0n1wnk=0
    证明: 由对称性 wnk+wnk+n/2=0k=0n1wnk=0
  7. 逆元存在:1wnk 存在。
    证明: 1wnk=eθi=(cos(θ)+isin(θ))=(cosθisinθ)wnk=eθi=(cosθ+isinθ) ,于是 1wnk=wnk 。其中 θ=Arg wnk=2kπn

1.5 C++ 中的复数类

不同于 C 中需要调用头文件,C++ 中直接有 complex 标准类。

  1. complex 类需要定义变量类型为 complex<float>complex<double>complex<long double>
  2. 一个 complex 类可以初始化变量 complex<T>z(cos(Arg),sin(Arg))Argdouble 类型的辐角。
  3. 一个 complex 类有成员函数 realimag ,可以访问实部和虚部。
  4. 一个 complex 类有常见的非成员函数 realimagabsarg ,返回复数的实部、虚部、模长、辐角。

2.多项式

2.1 多项式简介

2.1.1 多项式定义

对于常数系数乘以幂函数的和式 aixi
如果是有限项相加,称为多项式,写作 f(x)=i=0naixis.t.aiZ
如果是无限项相加,成为幂级数,写作 f(x)=i=0aixis.t.aiZ 。幂级数可以列项相消。

2.1.2 多项式的阶和度

对于多项式 f(x)=i=0naixi ,可以详细称作:关于 xn 阶多项式。

x 的最高次项的系数称为 degf ,也可以叫做 f(x) 的阶。形式上 degi=0naixi=n

2.2 多项式表示

2.2.1 多项式系数表示

多项式的系数表示即:f(x)=i=0naixi 。计算复杂度为 O(n)

2.2.2 多项式点值表示

先断言:一组横坐标不同的 n+1 个点对可以表示一个 n 阶多项式。
f(x) 的点值表示为: f(x)={(p0,f(p0)),(p1,f(p1)),(p2,f(p2)),,(pn,f(pn))}

证明:
不妨让 f(x)=i=0naixi ,将横坐标不同的 x0,x1,x2,,xn 带入 f(x) 得到 y0,y1,y2,,yn

  1. 唯一性证明:
    将方程组写成矩阵形式:

V=[1x01x02x0n1x11x12x1n1x21x22x2n1xn1xn2xnn]A=[a0a1a2an]B=[y0y1y2yn]

VA=B

显然 V 是个 Vandermonde 矩阵,是给个经典的满秩矩阵。矩阵满秩是个描述性名词,实际上和下述两个性质满足充要关系:

  • 矩阵可逆(即有逆元)
  • 行列式不为 0(即行向量线性无关、列向量线性无关,即有唯一解)

详见:https://www.cnblogs.com/zsxuan/p/18057134

于是

A=V1B

A 有唯一解。

  1. 正确性证明:
    唯一性证明完毕的基础下,正确性构造一下就成立了。
    显然将一组不同的 x0,x1,x2,,xny0,y1,y2,,yn 代入方程组,得到的 A 是唯一的且和 f(x)=i=0naixi 中的系数相等。

2.2.3 多项式系数表示与点值表示的朴素转化

朴素的系数表示转点值表示:求出 n+1 个点即可,时间复杂度 O(n2)
朴素的点值表示转系数表示:横坐标非连续的情况下,通过拉格朗日插值 O(n2) 得到。

2.3 多项式加法与等差前缀和升阶定理

多项式加法:
系数表示下:若 f(x)=i=0naixig(x)=i=0nbixi ,则 f(x)+g(x)=i=0n(ai+bi)xi
点值表示下: f(x)+g(x)={(p0,f(p0)+g(p0)),(p1,f(p1)+g(p1)),(p2,f(p2)+g(p2)),,(pn,f(pn)+g(pn))}
时间复杂度 O(n)

只讨论系数表示意义下的多项式等差前缀和:
多项式等差前缀和:x=0mi=0nai(u+vx)i=j=0n+1bjmj
等差前缀和升阶:f(x) 经过等差前缀和后成为了 g(m)degg=degf+1 。前缀和是平凡的等差前缀和。
时间复杂度 O(m)
如果有必要,多项式点值表示可以转化为多项式系数表示再进行前缀和。

2.4 多项式卷积

2.4.1 多项式乘法

多项式卷积即多项式乘法

定义 hfg 的卷积,即 h(x)=f(x)g(x)
显然地 degh=degf+degg=n+m

2.4.2 多项式系数表示下的卷积:

不考虑类似生成函数的角度,只考虑朴素的系数卷积。
定义 f(x)=i=0naixi,g(x)=i=0mbixi
从 DP 的角度考虑转移方程:ck=aixibki
则有:

h(x)=i=0n+mj=0iajbijxi

算法的时间复杂度是 O(n+m)2 的。

2.4.3 多项式点值表示下的卷积:

fg 取相同的横坐标,不妨定义 nm ,若否等同 swap(f,g)g 在升阶后只需要在空缺位补 0
定义 f(x)={(p0,f(p0)),(p1,f(p1)),(p2,f(p2)),,(pn,f(pn))}g(x)={(p0,f(p0)),(p1,f(p1)),(p2,f(p2)),,(pm,f(pn))}
g(x)=f(x)+g(x)=(p0,f(p0)+g(p0)),(p1,f(p1)+g(p1)),(p2,f(p2)+g(p2)),,(pn,f(pn)+g(pn))
算法的时间复杂度是 O(n) 的。

2.4.4 多项式快速卷积

可以提出爆论: 现实中遇到的需要处理的某个多项式几乎都是系数表示。且很多时候需要计算多项式在系数表示下的卷积。

是否可以避开系数卷积?即将系数转为点值,在点值意义下计算卷积,再转回系数?
显然这个做法的卷积复杂度为 O(n) ,但变换复杂度为 O(n2) ,于是 O(n2) 成为瓶颈。

这时候需要引入多项式快速变换算法。

2.4.5 常见多项式卷积

3.DFT

DFT 即离散傅里叶变换,可以快速将多项式系数表示变换成点值表示。

对于一个 n 阶多项式 f(x) ,不妨让 len2log2(n+1) ,并让多项式升阶至 len1 ,空缺位补 0

  1. log2x=31__builtin_clz(x) s.t. 0<x232
  2. log2x=31__builtin_clz(x)+e(__bulitin_popcount(x)>1) s.t. 0<x232

证明:

  1. __builtin_clz 和 __builtin_popcount 传入 unsigned int 。
  2. 2^{31 - 31} = 1。
  3. 当且仅当 __built_popcount(x) >= 2 时有进位。

于是 f(x) 的项数为 2k ,显然地可以分治。

F(x)=a0x0+a1x1+a2x2++anxn=(a0x0+a2x2+a4x4++an1xn1)+(a1x1+a3x3+a5x5++anxn)=(a0x0+a2x2+a4x4++an1xn1)+x(a1x0+a3x2+a5x4++anxn1)G(x)=(a0x0+a2x1+a4x2+an1x(n1)/2)H(x)=(a1x0+a3x1+a5x2+anx(n1)/2)则有F(x)=G(x2)+xH(x2)

其中 degG=degH=12degF 。可以令 G=F,H=F 继续分治。
考虑计算复杂度,每次向下递归,需要计算的函数都会倍增。
于是可以 T(1+2+4++n)=O(llogl) 计算出 F(x)
然而这个分治有什么意义?

考虑将 x 替换成 wlk ,则有:

F(wlk)=G(wl2k)+wlkH(wl2k)=G(wl/2k)+wlkH(wl/2k)F(wlk+l/2)=H(wl2k+l)+wlk+l/2G(wl2k+l)=G(wl2k)+(wlk)H(wl2k)=G(wl/2k)wlkH(wl/2k)

其中 l 为大于 12 的幂次。

这意味着我们只需要求出 G(wl/2k),H(wl/2k) 即可得到 F(wlk),F(wlk+l/2)

于是 nF(wl) 可以由 l/2G(wl/2)l/2H(wl/2) 得到。然后继续分治。

考虑基于特列来模拟理解这个过程,列举每个递归层的单位根折半情况:

{w80, w81, w82, w83, w84, w85, w86, w87}{w40, w41, w42, w43}{ w40, w41, w42, w43}{w20, w21}{ w20, w21}{ w20, w21}{ w20, w21}{w10}{w10}{w10}{w10}{w10}{w10}{w10}{w10}

显然 m 次单位根的函数 Ywm 可以由 m/2 次单位根的函数 Ywm/2 算出。

  1. 枚举 m{2,4,8,,l} 表示正在计算 m 次单位根的函数 Ywm
  2. 计算 m 次单位根 wm1=(cosArg,sinArg) 。辐角 Arg=2πm
  3. 显然数组会被分为 l/m 段,每段长度为 m ,代表一个函数。于是枚举 0j<l,j:=j+m 表示每段函数的起点。
  4. 对于每段长度为 m 的函数,枚举 jk<j+m/2 计算 f(wmk)f(wmk+m/2)

代码类似

for (int m = 2; m <= l; m *= 2) { // 枚举需要计算的 m 次单位根函数
double Arg = 2 * PI / m;
CD wm(cos(Arg), sin(Arg));
for (int j = 0; j < l; j += m) { // 枚举起点
CD wmi = 1;
for (int k = j; k < j + m / 2; k++) { // 折半计算
// f[k] = xxx, f[k + m / 2] = xxx;
wmi *= wm;
}
}
}

4.FT 蝶变

4.1 蝶变复写算法

观察
F(wmk)=G(wm/2k)+wmkH(wm/2k)
F(wmk+m/2)=G(wm/2k)wmkH(wm/2k)

分析单位根的折半图:

  1. G(wm/2k)H(wm/2k) 的两个位置只能影响到 F(wmk)F(wmk+m/2) 的两个位置。
  2. F(wmk) 的位置与下层 G(wm/2k) 的位置一样。
  3. F(wmk+m/2) 的位置与下层 H(wm/2k) 的位置一样。
    于是这四个位置可以直接复写,而不需要开额外空间。
    代码类似
complex<double> u = a[k], v = wmi * a[k + m / 2];
a[k] = u + v; a[k + m / 2] = u - v;

4.2 FT 蝶变定理

显然单位根的折半不会打乱顺序,但常数系数的折半会。
这里进行一些模拟

{x0, x1, x2, x3, x4, x5, x6, x7}{x0, x2, x4, x6}{ x1, x3, x5, x7}{x0, x4}{ x2, x6}{ x1, x5}{ x3, x7}{x0}{x4}{x2}{x6}{x1}{x5}{x3}{x7}

基于这个模拟,提出一个爆论
一个排列 p 分治地进行奇偶拆分后,得到的最终排列 q ,满足 qi=pR(i)
R(i)i 的二进制逆序后得到的数。

证明这个爆论正确的方法是,找不到模拟的反例。
于是该爆论可以视为定理。

需要先将常数系数置换到终点位置,才能从终点倍增回答案。于是有位逆序置换算法。

4.3 位逆序置换

4.3.1 位逆序变换算法

设二进制长度为 kx 的位逆序为 R(x) s.t. 0x2k1
考虑一件事:x 右移一位 等于 x >> 1R(x) 左移一位 等于 R(x >> 1)
于是 x 右移一位,再逆序,再右移一位,便可得到 x & (2k2) 的位逆序。即 x 的第一位与上 0 后的位逆序。
于是将结果或上 (x & 1)×2k1 即可得到 x 的位逆序。
写成公式即

R(x)=R(x >> 1) >> 1+(x & 1)2k1

2k=len ,有

R(x)=R(x >> 1) >> 1+(x & 1)(len >> 1)

显然 x >> 1<x ,于是可以递推。枚举复杂度 O(n) ,转移复杂度 O(logn) ,于是递推复杂度为 O(nlogn)

4.3.2 位逆序置换算法

考虑如何将权值 a0,a1,a2,,an1 换成 aR(0),aR(1),aR(2),,aR(n1)

不开额外空间的置换只能使用 swap 。当 swap(ai,aR(i)) 后,iR(i) 位置成为答案。

观察到性质 R(R(i))=i 。即数组中二元组 (i,R(i))(R(i),i) 成对。则若线性遍历 i 执行 swap(ai,aR(i)) ,算法结束后数组不变。

一个朴素的想法是开一份空间 vis 。正向线性遍历 i ,若 visi=0 ,则修改 ai=bR(i) ,并令 visi=visR(i)=1

有不开额外空间的办法吗?

正向遍历,借助 vis 数组观察算法特性。

  1. i=R(i) ,已经是答案。不妨默认为 visi=1
  2. visi1swap(ai,aR(i)) ,并 visi=visR(i)=1

可以断言若 visi1 ,则 i<R(i)

  1. iR(i) 显然。
  2. i>R(i) ,则 R(i)<R(R(i)) ,即 R(i) 会先于 i 被标记,与 visi1 矛盾。

这意味着只有 i<R(i) 的部分需要操作。

于是位逆序置换算法为,正向线性遍历 i ,若 i<R(i)swap(ai,aR(i))

5.IDFT

IDFT 即离散傅里叶逆变换,可以快速将多项式点值表示变换成系数表示。

一般 DFTIDFT 合称 FDFT ,快速(离散)傅里叶变换。在计算机领域中通常直接称作 FFT

6. 原根在 NTT 中的性质

详见:https://www.cnblogs.com/zsxuan/p/18099744

7.NTT

posted @   zsxuan  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示