[算法学习] 多项式全家桶

多项式

一个\(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))\)

猜你喜欢

转载自www.cnblogs.com/wlzhouzhuan/p/12657174.html
今日推荐