多项式
一个\(n\)次多项式可以表示为\(A(x)=\sum_{i=0}^{n}a_i x^i\),另一个\(n\)次多项式可以表示为\(B(x)=\sum_{i=0}^{n}b_i x^i\)。
- 多项式加法
将\(A(x)\)和\(B(x)\)相加,得到多项式\(C(x)=\sum_{i=0}^{n} (a_i+b_i) x^i\)。
复杂度是\(O(n)\)的。 - 多项式乘法
将\(A(x)\)和\(B(x)\)相乘,得到多项式\(C(x)=\sum_{i=0}^{n}\sum_{j=0}^{n}a_ib_jx^{i+j}\)。
复杂度是\(O(n^2)\)的,不是很优,于是我们决定想办法来解决它。
快速傅里叶变换 (FFT)
概述
快速傅里叶变换,英文名\(Fast\ Fourier\ Transform\),它可以在\(O(nlog(n))\)的复杂度内完成多项式乘法。
前置技能
函数的表达方法
- 系数表达法
通过\(a_0,a_1,...,a_n\)来表示函数\(f(x)=\sum_{i=0}^{n}a_ix^i\) - 点值表达法
选取平面上\(n+1\)个不同的点来表示函数\(f(x)=\{ (x_0,y_0), (x_1,y_1), ..., (x_n, y_n)\}\)
我们发现,通过点值表达法,我们可以在\(O(n)\)的复杂度内计算出\(C(x)\),于是我们考虑将系数和点值结合起来。
单位复数根
在复平面上,单位圆有一些其妙的性质:
我们默认\(n=2^t,t\in N\)
- \(w_n^k=w_{2n}^{2k}\)
- \(w_n^{k+\frac{n}{2}}=-w_n^k\)
- \(w_n^k=w_n^{k+n}\)
- 对于任意\(k\),均满足\(\sum_{j=0}^{n-1}(w_n^k)^j=0\)
推导
默认\(n=2^t,t\in N\),不足的位置上系数置为\(0\),令函数\(f(x)=a_0+a_1x+a_2x^2+...+a_nx^n\)
那么\(f(x)=(a_0+a_2x^2+a_4x^4+...+a_nx^n)+(a_1+a_3x^2+a_5x^4+...+a_{n-1}x^{n-2})x\)
令\(A(x)=a_0+a_2x+a_4x^2+...+a_nx^{\frac{n}{2}}\),\(B(x)=a_1+a_3x+...+a_{n-1}x^{\frac{n-2 }{2}}\),
则\(f(x)=A(x^2)+B(x^2)x\)。
代入\(x=w_n^k\),有\(f(w_n^k)=A(w_n^{2k})+B(w_n^{2k})w_n^k=A(w_{\frac{n}{2}}^{k})+B(w_{\frac{n}{2}}^{k})w_n^k\);
代入\(x=w_n^{k+\frac{n}{2}}\),有\(f(w_n^{k+\frac{n}{2}})=A(w_n^{2k+n})+B(w_n^{2k+n})w_n^{k+\frac{n}{2}}=A(w_{\frac{n}{2}}^{k})-B(w_{\frac{n}{2}}^{k})w_n^k\)。
我们把两式放在一起:
\(\begin{cases} f(w_n^k)=A(w_{\frac{n}{2}}^{k})+B(w_{\frac{n}{2}}^{k})w_n^k \\ f(w_n^{k+\frac{n}{2}})=A(w_{\frac{n}{2}}^{k})-B(w_{\frac{n}{2}}^{k})w_n^k \end{cases}\)
发现刚好一个加号一个减号,并且下标由\(n\)变为\(\frac{n}{2}\),因此直接递归下去即可。
时间复杂度 \(O(nlog(n))\)。