FFT算法学习笔记

Posted RRRR_wys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFT算法学习笔记相关的知识,希望对你有一定的参考价值。

写在前边

  1.辣鸡RRRR_wys之前csdn的博客,千年不更。。。还很水。。。于是开了这个Blog。。。妄图拯救一下自己

  2.最近接触接触了一些多项式理论。于是翘掉了愉快的高频,通过《算导》稍稍学习了一下

  3.算法竞赛中,FFT主要解决多项式的乘法等问题

FFT基本概念

  1.FFT即快速傅里叶变换, 是离散傅里叶变换的加速算法。可以在o(nlogn)的时间内,完成DFT和DFT-1

  2.DFT即离散傅里叶变换, 这里主要就是多项式的系数向量转换成点值表示的过程

多项式的表示

  1.系数表达:对于一个次数上界为n的多项式 A(x)=∑(j=0 - n-1) aj*xj 而言,系数表达式便是由系数组成的向量a = (a0, a1, a2, a3, ... , an-1)

         (1)计算A(x0)的值即:A(x0) = a0+x0(a1+x0(a2+x0(a3+x0(a4+...+x0(an-2+x0*an-1))...)))  时间为o(n)

    (2)通过系数向量计算两个多项式的乘法:设输出向量为c, 而a,b长度n=max(na,nb)那么显然两个c的长度为2n-1,计算方法为:cj = ∑(k=0 ~ j) ak*bj-k

        即向量a,b的卷积

  2.点值表达式:对于一个次数上界为n的多项式 A(x)=∑(j=0 ~ n-1) aj*xj 而言,点值表达式便是由n个点值所构成的集合{ (x0,y0), (x1,y1), (x2,y2), ... , (xn-1,yn-1) }

      (1)运用之前提到的方法,一个个计算点值时间为o(n2),之后可以看到如果我们巧妙地选取点xk可以使时间变为o(nlogn)

      (2)将点值表达式转换为系数表达式:将已知的点值带入,多项式可已得到一个有n个未知数的n个线性方程

     a0 + a1*x0 + a2*x02 + a3* x03 + ... + an-1*x0n-1 = y(1)

     a0 + a1*x1 + a2*x12 + a3* x13 + ... + an-1*x1n-1 = y(2)

     .......

     a0 + a1*xn-1 + a2*xn-12 + a3* xn-13 + ... + an-1*xn-1n-1 = yn-1 (n)

      可以写成矩阵形式,既为一个范德蒙矩阵,通过线代知识解这个方程就可以求出系数向量,复杂度o(n3)。另一种方法是采用拉格朗日插值法求解,复杂度o(n2)。因此,n个点的求值运算和插值运算,是定义完备的互逆运算。

    (3)通过点值计算两个多项式的乘积,c = { (x0,yA0*yB0), (x1,yA1*yB1), (x2,yA2*yB2), ... , (xn-1,yA(n-1)*yB(n-1)) }, 可以看到复杂度为o(n)

     (4)计算多项式乘法的过程:1)o(nlogn)分别求出两个多项式的点值表达式 2)点值乘法o(n) 3)插值o(nlogn) 4)求出答案多项式的系数表达式

DFT与FFT

  下面开始讨论,如何在o(nlogn)的时间内,完成求值和插值运算

  1.单位复数根

      n次单位复数根满足ωn=1的复数ω,n此单位复数根的数目恰好有n个,这些根是:ωnk = e2πik/n 这n个根均匀的分布在复平面上,其他n次单位根都是ωn的幂次。n个n次单位根在乘法意义下形成一个群,该群与模n意义下的加法群,有相同的结构,即ωni ωnj = ωn(i + j) mod n

   (1) 消去引理:ωndkd nk  (n>=0, k>=0, d>0)

   (2) ωnn/2 2 =-1

   (3) 折半引理:如果n>0为偶数,那么n个n次单位复数根的平方的集合就是n/2个n/2次单位复数根的集合

   (4) 求和引理:(j=0 ~ n-1) nk)j = 0 (n>=1, 不能被n整除的非负整数k)

  2.DFT

  我们希望计算ωn0, ωn1, ωn2, .... , ωnn-1处的值(在多项式乘法中其实是2n个点值)。假设给定系数a=(a0, a1, a2, ... , an-1), 即对于k=0, 1, 2, 3, ... , n-1求出yk = A(ωnk),记向量y=(y1, y2, y3, ... ,yn-1)就是系数向量a的离散傅里叶变换DFT,记为 y = DFTn(a)

  3. FFT

  通过快速傅里叶变换FFT,利用单位复数根的性质,我们可以在o(nlogn)的时间内计算DFTn(a)。首先假设次数n恰好是2的整数幂,不足在高次位置项添0。

  定义两个新的次数界为n/2的多项式 A[0] = a0 + a2*x + a4*x2 + a6* x3 + ... + an-2*xn/2-1 , A[1] = a1 + a3*x + a5*x2 + a7* x3 + ... + an-1*xn/2-1

  A[0]包含所有偶数下标的系数,A[1]包含所有奇数下标的系数,于是有A(x) = A[0](x2) + x*A[1](x2) 。

  所以,求解A(x)的DFN,转换为了求解多项式A[0], A[1]n0)2, (ωn1)2, (ωn2)2 , ... , (ωnn-1)2 处的取值。

  根据折半引理,n0)2, (ωn1)2, (ωn2)2 , ... , (ωnn-1)2 并不是由n个不同的值组成,而是由n/2个n/2次单位根复数根所组成,每个根正好出现两次。因此,我们递归的对次数界为n/2的多项式A[0], A[1]在n/2个n/2次单位复数根处进行求值。

 

以上是关于FFT算法学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

[学习笔记] 多项式与快速傅里叶变换(FFT)基础

[2017.12.2]FFT学习笔记

模意义下的FFT算法

快速傅里叶变换学习笔记

FFT 深夜摸鱼小笔记

FFT 学习笔记(自认为详细)