快速傅里叶变换(FFT)学习笔记(未完待续)


总所周知,FFT是一个非常麻烦的算法,再加上博主语文不好,便写起来有点麻烦,但会尽力去写。 要以后自己看不懂就。。。

注:因为最近的压力紧张,便没有继续学习FFT,这仅为目前的半成品以及一些目前已知的优化。

参考资料

讲解1

讲解2

优化

毛啸大佬的论文(不放上下载地址,因为下载论文的主要OJ太卡)

优化2

优化证明

题解

因为此篇文章比较依赖这些文章,为此先放出来。

FFT

吹水

FFT到底是干什么的?法法塔清小怪,不不不,人家的全名叫快速傅里叶变换。听说与傅里叶没有半毛钱关系。

FFT能解决两个多项式相乘。

例如:
a 2 x 2 + a 1 x 1 + a 0 a_{2}x^{2}+a_{1}x^{1}+a_{0} a2x2+a1x1+a0 b 2 x 2 + b 1 x 1 + b 0 b_{2}x^{2}+b_{1}x^{1}+b_{0} b2x2+b1x1+b0相乘,便可以算出 x 4 , x 3 , x 2 , x 1 , x 0 x^{4},x^{3},x^{2},x^{1},x^{0} x4,x3,x2,x1,x0的系数,在 O ( n l o g n ) O(nlogn) O(nlogn)的时间,而暴力要 O ( n 2 ) O(n^{2}) O(n2)

例题

例题

普通做法

上联:打表过样例,暴力出奇迹。

下联:花中一片叶,luogu两行泪。

。。。

更高大尚的做法

于是,就有人开始尝试新的做法了!

尝试方法

说到底,FFT究竟是什么?

大概样子:

系数表达式->点值表达式->点值相乘->系数表达式

现在,就为大家一一刨析做法!

定义与一部分性质

没学过多项式的估计你还没学OI呢,~~神童?~~默认大家会一点多项式的定义。

咱们先理清我说的一些十分玄学的话。

系数表达式

A ( x ) A(x) A(x)表示一个n?1次多项式

A ( x ) = p = ∑ i = 0 n a i ? x i A(x)=p = \sum_{i=0}^{n} ai?xi A(x)=p=i=0nai?xi
例如: A ( 3 ) = 2 + 3 ? x + x 2 A(3)=2+3?x+x^{2} A(3)=2+3?x+x2

这就是个系数表达式。

—以上摘自(http://www.cnblogs.com/zwfymqz/p/8244902.html#_label1_1)

点值表达式

这个就比较玄学,其实每一个n次的系数表达式都可以用n+1个点表是,将n+1个不同的值代入系数表达式,得出了n+1个点值 ( x , y ) (x,y) (x,y),而这n+1个点值就是这个系数表达式的点值表达式。


性质1

为什么n+1个点可以表示n次表达式,年轻人,我跟你共呀。

我们列一个n次方程: a n x n + a n − 1 x n − 1 + . . . + a 1 x 1 + a 0 = y a_{n}x^{n}+a_{n-1}x^{n-1}+...+a_{1}x^{1}+a_{0}=y anxn+an1xn1+...+a1x1+a0=y,将n+1个x,y带进去,列出一堆a的连七八糟的方程,用高斯消元便可以解出这个方程了。


点值相乘???

首先,系数相乘要 n 2 n^{2} n2,但是我们想想看点值相乘有没有可能乘出系数相乘后的表达式的点值?如果可以的话,岂不是 O ( n ) O(n) O(n)乘完?

明显,传说有个大佬想到了这一点,于是轻微的证了一下:

C ( x ) = A ( x ) ∗ B ( x ) C(x)=A(x)*B(x) C(x)=A(x)B(x)

所以

C ( 0.5 ) = A ( 0.5 ) ∗ B ( 0.5 ) C(0.5)=A(0.5)*B(0.5) C(0.5)=A(0.5)B(0.5)

这与点值有什么关系?

把0.5带到A(x)与B(x)不就是点值了,相乘不就是A(0.5)*B(0.5)了想乘了?

证毕。

在这里插入图片描述

但是,由于乘积后的多项式是2n次多项式,因此原本的两个多项式也需要准备2n+1个点来得出最后的多项式。

只可惜,点值相乘确实牛逼,但是转成点值并且如何转回来更难

卷积

两个多项式的乘积就是他们的卷积。

复数

数轴上的点是实数,但是二维坐标系中的点如何用一个表达式表示呢?一个巨人一巴掌拍成了数轴就可以了。。。

我们看一张图:

在这里插入图片描述

看,这个点的x坐标可以用实数表示,但y坐标。。。

还是(x,y)友好

于是就有大佬发明了个单位i,就是传说中的复数单位,i有个性质, i 2 = − 1 i^{2}=-1 i2=1

于是这个点的表示就是4+5i

于是大佬好人做到底,送佛送到西

大佬们又发明了复数运算。

仅介绍与FFT有关的运算。

复数相加: ( a + b i ) + ( c + d i ) = ( a + c ) + ( b + d ) i (a+bi)+(c+di)=(a+c)+(b+d)i (a+bi)+(c+di)=(a+c)+(b+d)i
复数相减: ( a + b i ) − ( c + d i ) = ( a − c ) + ( b − d ) i (a+bi)-(c+di)=(a-c)+(b-d)i (a+bi)(c+di)=(ac)+(bd)i
复数相乘: ( a + b i ) + ( c + d i ) = a c + a d i + b c i + d b i 2 = ( a c − b d ) + ( a d + b c ) i (a+bi)+(c+di)=ac+adi+bci+dbi^{2}=(ac-bd)+(ad+bc)i (a+bi)+(c+di)=ac+adi+bci+dbi2=(acbd)+(ad+bc)i
复数的共轭: a + b i = a − b i a+bi=a-bi a+bi=abi

复数相乘的二维意义就是模长相乘,幅角相加。

证明来源于https://www.luogu.org/blog/command-block/fft-xue-xi-bi-ji
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

单位根

其实,FFT就是DFT加上IDFT

DFT是什么

DFT就是一个能在 O ( n l o g n ) O(nlogn) O(nlogn)内将系数表达式转成点值表达式

我们平常把系数表达式转成点值表达式不就是一个个代,然后就 O ( n 2 ) O(n^{2}) O(n2)

但是,其实有一个神奇的东西,估计大家很熟悉,叫单位根。

放入大佬(https://www.luogu.org/blog/command-block/fft-xue-xi-bi-ji)的讲解:

n次单位根(n为正整数)是n次幂为1的复数!

到这里你也许会有一点不懂,我们来一起推导一下。

换句话说,就是方程 x n = 1 x^{n}=1 xn=1的复数解。

学过三角函数(解三角形)的童鞋应该对单位圆很熟悉

不熟悉的话也没事,单位圆就是:

圆心在原点且半径为1的圆(如图)

在这里插入图片描述

我们在复平面上放一个单位圆,在这个单位圆上的点表示的复数都有一个性质:

模长为1(圆上每一点到圆心的距离都相等)

可还记得?n次单位根是n次幂为1的复数

1的模长就是1

想象一个复数 x 。

如果 ∣ x ∣ > 1 |x|>1 x>1 ,即 ∣ x n ∣ = ∣ x ∣ n > 1 |x^{n}|=|x|^{n}>1 xn=xn>1 (模长乘模长,越乘越大)

如果 ∣ x ∣ < 1 |x|<1 x<1, 即 ∣ x n ∣ = ∣ x ∣ n < 1 |x^{n}|=|x|^{n}<1 xn=xn<1 (模长乘模长,越乘越小)

所以只有模长等于1的复数才有可能成为n次单位根。

所以只有模长等于1的复数才有可能成为n次单位根。

也就是说,只有单位圆上的点表示的复数才有可能成为n次单位根
我们成功缩小了探究范围,只在这一个圆上研究。

(下面提及的复数,均是在单位圆上的复数!!!)
想象一个模长为1的复数为 X X X ,设它的幅角为(圆周 ∗ a *a a )

(这里 0 < = a < 1 0<=a<1 0<=a<1 ,不然会产生重复)

它的n次方的幅角为 n a ? na? na? 圆周

那么,如果它是n次单位根,幅角的n倍 ( n a ? na? na? 圆周 ) 一定是圆周的自然数倍。

得到不定方程(听到这个名字别害怕):

( n a ? na? na? 圆周 ) = 圆周 ? k ?k ?k (k 为自然数)

等式两边同除以“圆周”

n a = k na=k na=k (k 为自然数参数)

分类讨论一下:

k = = 0 k==0 k==0

由于 n > 0 n>0 n>0 (方程的次数是正整数)只有 a = 0 a=0 a=0 这一种情况

k > 0 k>0 k>0

k k k 可以为 0 , 1 , 2 , 3... 0,1,2,3... 0,1,2,3...

k k k为1时,得 n a = 1 , a = 1 / n na=1,a=1/n na=1,a=1/n

k k k为2时,得 n a = 2 , a = 2 / n na=2,a=2/n na=2,a=2/n

n a = k , a = k / n na=k, a=k/n na=k,a=k/n

但是, k > 0 k>0 k>0 时并没有无数个单位根,他们会重叠,重叠的只算一个。

k = n k=n k=n 时,得 n a = n , a = n / n = 1 na=n,a=n/n=1 na=n,a=n/n=1

这就相当于绕了单位圆一圈又回到了起点,与k为0时没什么不同。

前面说 0 < = a < 1 0<=a<1 0<=a<1 ,到这里就该打住。

所以本质不同的单位根是 0 < k < n 0<k<n 0<k<n n − 1 n-1 n1 个单位根,共 n n n个。

综上所述, k = = 0 k==0 k==0 时必有一个单位根, k > 0 k>0 k>0 时有 n − 1 n-1 n1个单位根,所以 n n n次单位根一共有 n n n个。

另一种理解方法:

根据代数基本定理,n次方程在复数域内有且只有n个根。

上面我们验证了,幅角为 0 , 1 n 圆周 , 2 n 圆周 , . . . , 1 圆周 0,\dfrac{1}{n}\text{圆周},\dfrac{2}{n}\text{圆周},...,1\text{圆周} 0,n1圆周,n2圆周,...,1圆周的单位根,共n个。

所以这些就是所有的单位根了。

还不懂也没关系,我们来实践一下。

设 n=3;n=3;

有一个模长为1的复数为3次单位根,它的幅角为(圆周 ? a ?a ?a )

它的3次方的幅角为 3 a ? 3a? 3a? 圆周

那么,如果它是3次单位根,幅角的3倍 ( 3 a ? 3a? 3a? 圆周 ) 一定是圆周的自然数倍。

所以3a是自然数。

a=0时,它的幅角为0(其实这个复数就是1)

a=1/3时,它的幅角为(圆周/3)

a=2/3时,它的幅角为(2圆周/3)

在这里插入图片描述

可以看出, n n n次单位根 n n n等分单位圆。

证明:

有幅角为 0 , 1 n 圆周 , 2 n 圆周 , . . . , 1 圆周 0,\dfrac{1}{n}\text{圆周},\dfrac{2}{n}\text{圆周},...,1\text{圆周} 0,n1圆周,n2圆周,...,1圆周的单位根,共n个。

每一个都比上一个"多转了" 1 n 圆周 \dfrac{1}{n}\text{圆周} n1圆周

所以n次单位根n等分单位圆。

(非常重要!)。

怎么称呼这些单位根呢

ω \omega ω” 是单位根的符号

我们从1开始(1一定是单位根),沿着单位圆逆时针把单位根标上号。

w n 0 = 1 w_{n}^{0}=1 wn0=1

w n 1 w_{n}^{1} wn1为第二个n次单位根

w n n − 1 w_{n}^{n-1} wnn1为第二个n次单位根

在这里插入图片描述
比如上图,最右边的点就是 ω 3 0 \omega_{3}^0 ω30
?

左上角的点就是 ω 3 1 \omega_{3}^1 ω31
?

左下角的点就是 ω 3 2 \omega_{3}^2 ω32

P.S
虽然我们只承认 ω n 0 , ω n 1 , ω n 2 \omega_{n}^0,\omega_{n}^1,\omega_{n}^2 ωn0,ωn1,ωn2~ ω n n − 1 \omega_{n}^{n-1} ωnn1

但是也有 ω n k \omega_{n}^{k} ωnk k > = n k>=n k>=n k < 0 k<0 k<0 的情况(学过带正负的角吗)。

所以 ω n k = ω n k % n \omega_{n}^k=\omega_{n}^{k\%n} ωnk=ωnk%n

随意称呼,切了书写方便,一般不取模。
?
关于单位根的基本定义相信你已经Get到了。

单位根的世界,就是一个单位圆。

摘抄完毕。(我不是博主,我只是博客的搬运工

当然单位根还有一系列要证的,再次,我形容一个抽象的概念帮助大家更好的食用。

我们可以把n次单位根平均切成n块,例如四次单位根:

在这里插入图片描述

而且我们可以证明它,不是说了吗, w n i w_{n}^{i} wni的n次方是1吗,也就是图中被圈的位置,我们把被圈上的单位根叫 w n 0 w_{n}^{0} wn0(注: w n 0 = 1 w_{n}^{0}=1 wn0=1),然后逆时针标上 w n 1 , w n 2 , w n 3 . . . w_{n}^{1},w_{n}^{2},w_{n}^{3}... wn1,wn2,wn3...

在这里插入图片描述

根据图中,我们可以知道, w n 1 w_{n}^{1} wn1的幅角为 1 ∗ 1* 1 360 n 360\over n n360度, w n 2 w_{n}^{2} wn2的幅角为 2 ∗ 2* 2 360 n 360\over n n360度… w n i w_{n}^{i} wni的幅角为 i ∗ i* i 360 n 360\over n n360度,那么 w n i w_{n}^{i} wni的n次方的幅角就是 w n i w_{n}^{i} wni的幅角乘以n,容易知道为360的倍数,所以就在 0 , 1 0,1 0,1的位置,所以可以知道,单位根连接原点的这几条线均分单位圆,用大佬的话来讲,就是将“蛋糕”分成了n份。

性质1 w n i ∗ w n j = w n i + j w^{i}_{n}*w^{j}_{n}=w_{n}^{i+j} wniwnj=wni+j

我们想呢,取i份蛋糕再取j份蛋糕不就是i+j份蛋糕?(复数乘法幅角相加)

性质2: ( w n i ) k = w n i k (w^{i}_{n})^{k}=w_{n}^{ik} (wni)k=wnik

我们想呀, w n i w_{n}^{i} wni就是取出“蛋糕”中的i份,而k次方就是k次取出其中的i份,不就是ki份了吗?

性质3: w k n k i = w n i w_{kn}^{ki}=w_{n}^{i} wknki=wni
显而易见,切kn刀拿ki份等价于n刀i份。

性质4: w n k + n / 2 = − w n k w_{n}^{k+n/2}=-w_{n}^{k} wnk+n/2=wnk( n n n被2整除)

这个比较抽象(貌似其他也很抽象),就是你现在有一个单位根,而加上了所谓的 n 2 n\over2 2n块蛋糕后,就相当于取了目前单位根的负数(旋转180度)

在这里插入图片描述
自己画几个图便可以理解。

于是,在千辛万苦之下,我们懂了单位根。

DFT

首先,我们不说一些BB的话了。

首先,DFT的本质就是分治同时利用数学的奇妙性质实现 O ( n l o g n ) O(nlogn) O(nlogn)的。

???

别急,我们一步步来,首先,我们把一个n次多项式(n可以写成 2 i − 1 2^i-1 2i1的形式,也就是说里面有 2 i 2^{i} 2i个项)按奇偶分开。

如: a 0 + a 1 x 1 + a 2 x 2 + a 3 x 3 a_{0}+a_{1}x^{1}+a_{2}x^{2}+a_{3}x^{3} a0+a1x1+a2x2+a3x3可以分成 a 0 + a 2 x 2 a_{0}+a_{2}x^{2} a0+a2x2 a 1 x 1 + a 3 x 3 a_{1}x^{1}+a_{3}x^{3} a1x1+a3x3

我们设 F ( x ) = a 0 + a 1 x 1 + a 2 x 2 + a 3 x 3 = ( a 0 + a 2 x 2 ) + ( a 1 x 1 + a 3 x 3 ) F(x)=a_{0}+a_{1}x^{1}+a_{2}x^{2}+a_{3}x^{3}=(a_{0}+a_{2}x^{2})+(a_{1}x^{1}+a_{3}x^{3}) F(x)=a0+a1x1+a2x2+a3x3=(a0+a2x2)+(a1x1+a3x3),我们再设两个函数: F L ( x ) , F R ( x ) FL(x),FR(x) FL(x),FR(x)

有: F ( x ) = F L ( x 2 ) + x ∗ F R ( x 2 ) F(x)=FL(x^{2})+x*FR(x^{2}) F(x)=FL(x2)+xFR(x2)

F L ( x ) , F R ( x ) FL(x),FR(x) FL(x),FR(x)是依赖于 F ( x ) F(x) F(x)的。
F L ( x ) = a 0 + a 2 x + . . . . . . . FL(x)=a_{0}+a_{2}x+....... FL(x)=a0+a2x+.......
F R ( x ) = a 1 + a 3 x + . . . . . . . FR(x)=a_{1}+a_{3}x+....... FR(x)=a1+a3x+.......

那么,我们就可以分治啦。

不是不是呀,我们只是分治了项数呀,但是要找的点数却不变,所以分治不顶用呀!

急什么。

不如重点。

性质1: F ( w n i ) = F L ( w n / 2 i ) + w n i ∗ F R ( w n / 2 i ) F(w_{n}^{i})=FL(w_{n/2}^{i})+w_{n}^{i}*FR(w_{n/2}^{i}) F(wni)=FL(wn/2i)+wniFR(wn/2i) ( i < n / 2 ) (i<n/2) (i<n/2)

我们怎么证?

F ( w n i ) = F L ( ( w n i ) 2 ) + w n i ∗ F R ( ( w n i ) 2 ) F(w_{n}^{i})=FL((w_{n}^{i})^{2})+w_{n}^{i}*FR((w_{n}^{i})^{2}) F(wni)=FL((wni)2)+wniFR((wni)2) ( i < n / 2 ) (i<n/2) (i<n/2)

因为 ( w n i ) k = w n k i (w_{n}^{i})^{k}=w_{n}^{ki} (wni)k=wnki

F ( w n i ) = F L ( w n 2 i ) + w n i ∗ F R ( w n 2 i ) F(w_{n}^{i})=FL(w_{n}^{2i})+w_{n}^{i}*FR(w_{n}^{2i}) F(wni)=FL(wn2i)+wniFR(wn2i) ( i < n / 2 ) (i<n/2) (i<n/2)

因为 2 ∣ n 2|n 2n并且 w 2 n 2 i = w n i w_{2n}^{2i}=w_{n}^{i} w2n2i=wni

F ( w n i ) = F L ( w n / 2 i ) + w n i ∗ F R ( w n / 2 i ) F(w_{n}^{i})=FL(w_{n/2}^{i})+w_{n}^{i}*FR(w_{n/2}^{i}) F(wni)=FL(wn/2i)+wniFR(wn/2i) ( i ≥ n / 2 ) (i≥n/2) (in/2)

这样我们就利用 n / 2 n/2 n/2次单位根推出了目前的 w n 0 , w n 1 , w n 2 . . . . . . , w n n / 2 − 1 w_{n}^{0},w_{n}^{1},w_{n}^{2}......,w_{n}^{n/2-1} wn0,wn1,wn2......,wnn/21

但是另一半呢?

性质2: F ( w n i + n / 2 ) = F L ( w n / 2 i ) − w n i ∗ F R ( w n / 2 i ) F(w_{n}^{i+n/2})=FL(w_{n/2}^{i})-w_{n}^{i}*FR(w_{n/2}^{i}) F(wni+n/2)=FL(wn/2i)wniFR(wn/2i) ( i < n / 2 ) (i<n/2) (i<n/2)

F ( w n i + n / 2 ) = F L ( ( w n i + n / 2 ) 2 ) + w n i + n / 2 ∗ F R ( ( w n i + n / 2 ) 2 ) F(w_{n}^{i+n/2})=FL((w_{n}^{i+n/2})^{2})+w_{n}^{i+n/2}*FR((w_{n}^{i+n/2})^{2})

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值