快速傅里叶变换(FFT,Fast Fourier Transform)是信号处理的常用手段,可以把时域信号变成频域信号,时域的卷积运算对应于频域就成了简单的乘法运算。由于两个多项式的乘积,其系数的运算实际上也是一种卷积运算,因此可以用FFT来计算多项式的乘法。网上关于FFT算法的讲解大多都是工程领域的,这里从算法竞赛的角度来剖析一下怎么简洁而高效的实现FFT。
一,为什么要用FFT来计算多项式乘法
众所周知,如果我们用普通的for循环来直接计算系数的话,算法的时间复杂度是O(N^2)级别的,算法慢的原因是因为我们是在用系数表达式计算的。而实际上,还有另外一种方法也可以完整的表达一个多项式,那就是点值表达式。通俗的说就是给出n个不同的Xi,求出对应的Yi,那么这n对(Xi,Yi)就可以准确的确定一个多项式的系数。那么如何通过点值表达式计算多项式相乘的系数呢?首先,我们计算得到n个A(Xi)和n个B(Xi),那么A(Xi)*B(Xi)就是多项式相乘后在Xi处的结果,这样就有n个A(Xi)B(Xi),可以唯一的确定一个多项式。然而,如果只是随意的选择n个点,计算出这n个点值的时间复杂度仍然是O(N^2)的,并没有丝毫改善。但是,如果我们巧妙的选取这n个点,就可以加速这一计算过程,使得计算出这n个点的时间复杂度降为O(NlogN)。这n个点就是n次单位复数根对应的点。
二,n次单位复数根的性质
FFT算法之所以可以很快就是利用了n次单位根的性质来加速计算的。下面就是用到的3条性质。
1. 消去引理
它的一个推论如下:
2.折半引理
它的一个推论如下: