像我这么弱的很多名词都不知道, 所以必须先看两遍算导。
然后看 这个人写的很清晰的FFT 就一定可以懂啦。
我再来balabala几句:
FFT就是要在 nlogn 的时间计算两个多项式的乘积。
具体思想是 既然 两个点值表达的多项式 相乘 时间复杂度是 线性的(显然), 那为何不把多项式转换为点值表达然后乘起来然后再转换成多项式表达呢?
事实证明这样做是可行的, 大致流程就是这样:
那么问题来了, 怎么把一个多项式转换成点值表达? 还是只能想到 n² 的方法是不是。
如果你很厉害的话, 看完上面那张图已经 got 到方法了就不用再看我balabala了。
因为你已经知道图片上 w 加一些上标下标什么的就是指单位复数根, 就快去拍代码吧。
如果你像我一样表示没有听说过它或者只卖萌是恰好想要复习一下, Root of unity --Wikipedia 是一个很好的选择。
单位根
【定义】
这方程的复数根 为
次单位根。
单位的 次根有
个:
。
可以证明 n 个 n 次单位根在复平面 是 均匀分布在 半径为 1 的一个圆周上的, 那么就会出现很多喜闻乐见的性质。
【要用到的性质】
下面,我们用N次单位根来表示
。
的性质:
- 周期性,
具有周期
,即
wn ^ (k + n) = (wn ^ k) * (wn ^ n) = (wn ^ k) * 1
2,对称性:。
∵ wn ^ (n/2) = e^iπ =-1 ∴wn^x= - wn^(x+n/2)
3,若是
的约数,
把 k = 2 代入, 即: wn ^ 2 = w(n / 2)
好了现在基础知识已经预备完毕, 可以考虑如何操作了。
考虑N-1阶多项式A(x),假定N是2的整数次幂(如果不是的话后缀默认是0 就行了)
显然如果N = 1, dft(N) = N。
其余情况把多项式按奇偶拆为两个N/2-1阶多项式:
A偶(x)=a0 + a2x + a4x^2 + ... + aN-2x^(N/2-1)
A奇(x)=a1 + a3x + a5x^2 +..+ aN-1x^(N/2-1)
那么, A(x)=A1(x^2)+xA2(x^2)
这个时候, A(x) 在 wn ^ 0, wn ^ 1, wn ^ 2 ....... wn ^ (n - 1) 处的点值就是要求
A偶 和 A奇 在 (wn ^ 0) ^ 2, (wn ^ 1) ^ 2 ............ (wn ^ (n / 2 - 1)) ^ 2 处的点值,
根据 上述 wn 的第三条性质, 即求 w(n / 2) ^ 0 , w(n / 2) ^ 1 ...... w(n / 2) ^ (n / 2 - 1) 处的点值。
这时候我们就已经成功将问题缩小到原来的 二分之一了!
现在递归的写法就很显然了:
但是我们看到在递归的伪代码中 第8 行和第9行干的事情实际上是一样的, 于是我们会想办法让它只算一次来优化。