多项式学习笔记
FFT
FFT就是利用单位根,实现 \(O(n\log n)\) 的将一个多项式 \(A(x)=\sum_{i=0}^{n-1} a_ix_i\) 由它的系数表示法转化为点值表示法,然后 \(O(n)\) 的与另一个多项式实现多项式乘法,然后再转化为系数表示法的过程。
FFT复杂度低的原因是它把 \(n\) 个\(A(x)\) 在系数和点值表示法之间转化变成 \(\frac{n}{2}\) 个
什么是单位根?想象一个画在复平面上的圆,半径为 \(1\) ,将这个圆 \(n\) 等分,从 \((1,0)\) 开始逆时针编号 \(0 \ - \ n-1\) ,那么每一个等分点就是一个单位根,其中第 \(k\) 个记作 \(\omega_n^k\)。
关于单位根有几个性质,FFT就是依靠这些性质来进行的:
1.\(\omega_n^k=(\omega_n^1)^k\)
这个比较显然,根据复数相乘时模相乘,幅角相加,可以从几何意义上理解。
2.\(\omega_{dn}^{dk}=\omega_n^k\)
依然是看图。
3.\(\omega_n^{k+\frac{n}{2}}=-\omega_n^k\)
二者正好差一个半圆。
那么现在就可以利用这些性质来优化本来是 \(O(n^2)\) 的DFT啦:
首先需要将 \(A(x)\) 的项数补成 \(2\) 的正整数次幂,方便后面计算。
将 \(A(x)\) 展开:
设:
\(A_0(x)=a_0x^0+a_2x^1+\cdots +a_{n-2}x^{\frac{n-2}{2}}\)
\(A_1(x)=a_1x^0+a_3x^1+\cdots +a_{n-1}x^{\frac{n-2}{2}}\)
然后可以发现:
那么假设现在要计算的是 \(A(\omega_n^k)\ \ (k<\frac{n}{2})\):
那当 \(k>\frac{n}{2}\) 时呢?因为这个 \(k\) 是枚举的,所以只要考虑怎么算出 \(A(\omega_n^{k+\frac{n}{2}})\) 就行了:
因为 \(\omega_n^{k+\frac{n}{2}}=-\omega_n^k\),所以:
然后我们发现,我们成功地把求 \(A(\omega_n^0)\ \ - \ \ A(\omega_n^{n-1})\) 转化为了求 \(A(\omega_n^0)\ \ - \ \ A(\omega_n^{ \frac{n}{2}-1})\),这样一直递归下去,复杂度就从 \(O(n^2)\) 优化到了 \(O(n\log n)\)。
那么现在我们成功地把系数表示法转换为了点值表示法,再怎么转回来呢?其实只要把跑出来的点值表示法当成系数,把 \((w_n^k)^{-1}\) 带入再FFT一次,再除以 \(n\) 就行了:
依然是设 \(k<\frac{n}{2}\)