FFT快速傅里叶变换
说明
- 本文创作的目的是为自己巩固该算法,加深印象并深入理解,同时也为FFT入门学者提供一份可鉴的学习总结。
- 原文链接:https://blog.csdn.net/qq_39565901/article/details/94648221
- 版权归作者所有,允许参考,转载需注明作者。
参考&鸣谢
小学生都能看懂的FFT!!!
十分简明易懂的FFT(快速傅里叶变换)
浅谈 FFT (终于懂一点了~~)
数学黑科技1——FFT
什么是FFT?
- FFT(Fast Fourier Transformation) 是离散傅氏变换(DFT)的快速算法。即为快速傅氏变换。它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。——百度百科
- 这是什么并不重要。。。
用来做什么?
- 标准的FFT模板题,
- 设两个多项式:
- A = ∑ i = 0 n a i ∗ x i = a n ∗ x n + a n − 1 ∗ x n − 1 + . . . + a 1 ∗ x + a 0 A=\sum_{i=0}^na_i*x^i=a_n*x^n+a_{n-1}*x^{n-1}+...+a_1*x+a_0 A=i=0∑nai∗xi=an∗xn+an−1∗xn−1+...+a1∗x+a0,
- B = ∑ i = 0 m b i ∗ x i = b n ∗ x m + b m − 1 ∗ x m − 1 + . . . + b 1 ∗ x + b 0 B=\sum_{i=0}^mb_i*x^i=b_n*x^m+b_{m-1}*x^{m-1}+...+b_1*x+b_0 B=i=0∑mbi∗xi=bn∗xm+bm−1∗xm−1+...+b1∗x+b0,
- 求 A ∗ B A*B A∗B的值?
- 难道不就是 A n s = ∑ i = 0 n + m s i ∗ x i = ∑ i = 0 n + m ∑ j = 0 i a j ∗ b i − j ∗ x i Ans=\sum_{i=0}^{n+m}s_i*x^i=\sum_{i=0}^{n+m}\sum_{j=0}^{i}a_j*b_{i-j}*x^i Ans=i=0∑n+msi∗xi=i=0∑n+mj=0∑iaj∗bi−j∗xi
- 是的,用 A A A的每一项和 B B B的每一项分别相乘,时间复杂度 O ( n m ) O(nm) O(nm).
- 但如何跑得更快呢?
- ——用FFT!
- 经典的应用,
- 高精度乘法(是不是十分显然)。
关于多项式
- 上面的多项式表示法是最普通的,也就是平时课本上看到的,称为“系数表示法“,因为显而易见每一项的系数分别是多少。
- 现在介绍另一种表示法——“点值表示法”,
- 一个 n n n次 n + 1 n+1 n+1项式,可以将其看做是 n n n次函数的解析式,
- 为了唯一确定这个 n n n次多项式,需要选取 n + 1 n+1 n+1个不同的 x x x代入该式子,分别得到一个对应的 y y y,
- 也就是,
- a n ∗ x 0 n + a n − 1 ∗ x 0 n − 1 + . . . + a 1 ∗ x 0 + a 0 = y 0 a_n*x_0^n+a_{n-1}*x_0^{n-1}+...+a_1*x_0+a_0=y_0 an∗x0n+an−1∗x0n−1+...+a1∗x0+a0=y0,
- a n ∗ x 1 n + a n − 1 ∗ x 1 n − 1 + . . . + a 1 ∗ x 1 + a 0 = y 1 a_n*x_1^n+a_{n-1}*x_1^{n-1}+...+a_1*x_1+a_0=y_1 an∗x1n+an−1∗x1n−1+...+a1∗x1+a0=y1,
- … … …… ……
- a n ∗ x n n + a n − 1 ∗ x n n − 1 + . . . + a 1 ∗ x n + a 0 = y n a_n*x_n^n+a_{n-1}*x_n^{n-1}+...+a_1*x_n+a_0=y_n an∗xnn+an−1∗xnn−1+...+a1∗xn+a0=yn,
- 那么就有两个多项式分别表示为(注意要取相同的且个数相同的 x x x),
- A = ( ( x 0 , y A 0 ) ) , ( x 1 , y A 1 ) , . . . , ( x n , y A n ) ) A=((x_0,{y_A}_0)),(x_1,{y_A}_1),...,(x_n,{y_A}_n)) A=((x0,yA0)),(x1,yA1),...,(xn,yAn))
- B = ( ( x 0 , y B 0 ) ) , ( x 1 , y B 1 ) , . . . , ( x n , y B n ) ) B=((x_0,{y_B}_0)),(x_1,{y_B}_1),...,(x_n,{y_B}_n)) B=((x0,yB0)),(x1,yB1),...,(xn,yBn))
- 则它们的积为,
- A n s = ( ( x 0 , y A 0 ∗ y B 0 ) , ( x 1 , y A 1 ∗ y B 1 ) , . . . , ( x n , y A n ∗ y B n ) ) Ans=((x_0,{y_A}_0*{y_B}_0),(x_1,{y_A}_1*{y_B}_1),...,(x_n,{y_A}_n*{y_B}_n)) Ans=((x0,yA0∗yB0),(x1,yA1∗yB1),...,(xn,yAn∗yBn))
- 把系数表示法变为点值表示法的运算叫做点值运算,
- 把点值表示法变为系数表示法的运算叫做插值运算,
- 这两种运算是互逆的,同时也一定是可逆的。
- 仿佛发现什么不可告人的秘密(难道就这么简单