序言
掌声鼓励,本蒟蒻终于学会FFT啦!
死磕了接近5天的FFT,中途断断续续,请教了所谓的“数论讲师”葛某。
他居然告诉我:
他不会!!!
他不会!!!
他不会!!!
他不会!!!
他不会!!!
他不会!!!
前排膜拜dalao
如果觉得本人蒟蒻的,勿喷,可以看这两位dalao的Blog:
Mikcoo
Picks
前排预警:这篇Blog有很多公式!!!
预备知识
数论dalao可以直接跳过了……
多项式
形如的称为多项式。
称为多项式的系数。
为不定元,不表达任何确定值。
不定元在多项式中最大的次数称为多项式的次数。
多项式的系数表达法
多项式的系数表示为维向量。 简单理解为一个数组就好……数学家总是喜欢搞些奇奇怪怪的东西。
多项式的点值表示法
已知对于一元次方程可以用个点的坐标表示。(理由自证)
多项式的点值表示为。
还可用点值向量
复数
形如的数称为复数,其中为实数,为虚数单位,满足’
单位根
次单位根为满足的复数,共有个,均匀的分布在复平面的单位圆上,将单位圆等分。
所以次单位根的算术表示为。
多项式乘法
给定两个多项式,求
系数表示法下的运算
易证时间复杂度为
点值表示法下的运算
的点值表示为
易证时间复杂度为
Fast Fourier Transformation
FFT在竞赛中一般用于加速多项式乘法运算。
现在引入FFT(Fast Fourier Transformation)。
我们观察到对于以上两种运算,点值表示法下的运算明显优于系数表示法下的运算,考虑将运算过程转移到点值表示法下。
使用暴力强行将系数表示法转换为点值表示法的时间复杂度是,这里不再做讨论。
FFT算法流程
英文看的辛不辛苦啊,我就不翻译。(手动滑稽)
Discrete Fourier Transform
DFT的目的是将系数向量转换为点值向量。
将个相异实数代入多项式。
的点值表示为
点值向量
点值向量称为系数向量的离散傅里叶变换(Discrete Fourier Transform),记作
易证上述做法时间复杂度为
Cooley-Tukey算法(蝶形算法)
以下摘自Wiki:
库利-图基快速傅里叶变换算法(Cooley-Tukey算法)[1]是最常见的快速傅里叶变换算法。这一方法以分治法为策略递归地将长度为N = N1N2的DFT分解为长度分别为N1和N2的两个较短序列的DFT,以及与旋转因子的复数乘法。这种方法以及FFT的基本思路在1965年J. W. Cooley和J. W. Tukey合作发表An algorithm for the machine calculation of complex Fourier series之后开始为人所知。但后来发现,实际上这两位作者只是重新发明了高斯在1805年就已经提出的算法(此算法在历史上数次以各种形式被再次提出)。
库利-图基算法最有名的应用,是将序列长为N的DFT分割为两个长为N/2的子序列的DFT,因此这一应用只适用于序列长度为2的幂的DFT计算,即基2-FFT。实际上,如同高斯和库利与图基都指出的那样,库利-图基算法也可以用于序列长度N为任意因数分解形式的DFT,即混合基FFT,而且还可以应用于其他诸如分裂基FFT等变种。尽管库利-图基算法的基本思路是采用递归的方法进行计算,大多数传统的算法实现都将显示的递归算法改写为非递归的形式。另外,因为库利-图基算法是将DFT分解为较小长度的多个DFT,因此它可以同任一种其他的DFT算法联合使用。
从中我们注意到一句话:“……因此这一应用只适用于序列长度为的幂的DFT计算……”。
所以,为了计算的方便,我们将位多项式补位至2的幂。(,高位补为)
将个单位根代入多项式。
的点值表示为
点值向量
现在Cooley-Tukey算法将每一项系数按指数奇偶分类,以此将系数减半:
现在我们考虑如何将代入的值也减半:
因为:
且当时
所以:
当时
需要代入的值有,问题转换为两个折半的子问题,可通过递归或迭代实现。
易证时间复杂度为。
至此,通过Cooley-Tukey算法,我们将DFT的时间复杂度降为。
Inverse Discrete Fourier Transform
IDFT的目的是将点值向量转换为系数向量
IDFT就相当于把DFT过程中的换成,然后做一次DFT,之后结果除以就可以了。
这里只给出结论,用兴趣的同学可以自行研究。(你就是懒得写)
总结
对于多项式的运算(高精度预算),使用FFT可以实现十分好的时空复杂度优化。