多项式算法——快速傅里叶变换FFT
目录
两个多项式函数相加的时间复杂度为 O ( n ) O(n) O(n),而相乘的时间复杂度为 O ( n 2 ) O(n^2) O(n2),即所有系数的笛卡尔积。傅里叶变换DFT将优化多项式相乘(以下简称卷积),而快速傅里叶变换则优化至 O ( n log n ) O(n \log n) O(nlogn)。
前置知识:
- 微积分(欧拉公式)
- 复变函数(单位元根)
- 线性代数(矩阵方程)
多项式
本章定义的多项式函数为定义在实数域上,关于变量 x x x形如:
A ( x ) = ∑ j = 0 n − 1 a j x j A(x) = \sum_{j=0}^{n-1} a_j x^j A(x)=j=0∑n−1ajxj
的 n n n次多项式, a j a_j aj为多项式的系数,如果多项式非零最高次数项的系数为 a k a_k ak,那么我们说 A ( x ) A(x) A(x)的次数为 k k k,记作 d e g r e e ( A ) = k degree(A)=k degree(A)=k。
任何一个严格大于多项式 A ( x ) A(x) A(x)的次数的整数都是多项式 A ( x ) A(x) A(x)的一个次数界。
多项式加法
两个次数界为 n n n的多项式 A ( x ) A(x) A(x)和 B ( x ) B(x) B(x)的多项式相加,仍是一个次数界为 n n n的多项式 C ( x ) C(x) C(x),点值满足 C ( x ) = A ( x ) + B ( x ) C(x)=A(x)+B(x) C(x)=A(x)+B(x),且系数满足:
C ( x ) = ∑ j = 0 n − 1 ( a j + b j ) x j C(x) = \sum_{j=0}^{n-1} (a_j + b_j) x^j C(x)=j=0∑n−1(aj+bj)xj
多项式乘法
两个次数界为 n n n的多项式 A ( x ) A(x) A(x)和 B ( x ) B(x) B(x)的多项式相乘,其结果是一个次数界为 2 n − 1 2n-1 2n−1的多项式 C ( x ) C(x) C(x)。点值满足 C ( x ) = A ( x ) B ( x ) C(x)=A(x)B(x) C(x)=A(x)B(x),且系数满足:
C ( x ) = ∑ j = 0 2 n − 1 ∑ i = 0 j a i b j − i x j C(x) = \sum_{j=0}^{2n-1} \sum_{i=0}^ja_i b_{j-i} x^j C(x)=j=0∑2n−1i=0∑jaibj−ixj
也称卷积。
多项式表示法
系数表示
对于一个次数为 n n n的多项式 A ( x ) = ∑ j = 0 n − 1 a j x j A(x) = \sum_{j=0}^{n-1} a_j x^j A(x)=∑j=0n−1ajxj而言,其系数表示法是一组由系数组成的 n n n维列向量 a ⃗ = ( a 0 , a 1 , … , a n − 1 ) \vec{a} = (a_0,a_1,\ldots,a_{n-1}) a=(a0,a1,…,an−1)。
对于给定的一个系数表示法的多项式,我们可以通过霍纳法则(秦九韶算法)在 O ( n ) O(n) O(n)时间内计算出点值 A ( x 0 ) A(x_0) A(x0),即:
A ( x 0 ) = a 0 + x 0 ( a 1 + x 0 ( a 2 + … + x 0 ( a n − 1 ) ) … ) ) A(x_0) = a_0 + x_0 (a_1 +x_0(a_2+\ldots+x_0(a_{n-1}))\ldots)) A(x0)=a0+x0(a1+x0(a2+…+x0(an−1))…))
同时,我们对两个系数表示法的多项式只需要 O ( n ) O(n) O(n)的时间内就能完成,只需要做一次向量加法即可。
现在考虑系数表示法的多项式相乘,需要在 O ( n 2 ) O(n^2) O(n2)的时间内完成,因为需要做一次向量卷积(笛卡尔直积),记作 c ⃗ = a ⃗ ∗ b ⃗ \vec{c} = \vec{a} \ast \vec{b} c=a∗b。
点值表示
一个次数界为 n n n的多项式的点值表示就是由一个 n n n个点值对所组成的集合:
{ ( x 0 , y 0 ) , … , ( x n − 1 , y n − 1 ) } \{(x_0,y_0),\ldots,(x_{n-1},y_{n-1})\} {(x0,y0),…,(xn−1,yn−1)}
y k = A ( x k ) y_k = A(x_k) yk=A(xk),使得所有取值点的 x k x_k xk均不相同。
一个多项式的取值点的不同,表达也不同,故一个多项式的点值表示并不唯一。我们统一取值点为一个固定的点集 x 0 , … , x n − 1 x_0,\ldots,x_{n-1} x0,…,xn−1,称为基底。
求值计算的逆(从点值表示法计算系数表示法的过程)叫做插值。
定理:只有点值集合的大小和多项式的次数界相同,其插值才是唯一的。
证明:
点值和插值可以由如下矩阵表示:
[ 1 x 0 ⋯ x 0 n − 1 1 x 1 ⋯ x 1 n − 1 ⋮ ⋮ ⋱ ⋮ 1 x n − 1 ⋯ x n − 1 n − 1 ] [ a 0 a 1 ⋮ a n − 1 ] = [ y 0 y 1 ⋮ y n − 1 ] \begin{bmatrix} 1& x_{0}& \cdots & x_{0}^{n-1}\\ 1& x_{1}& \cdots & x_{1}^{n-1}\\ \vdots & \vdots & \ddots & \vdots \\ 1& x_{n-1}& \cdots & x_{n-1}^{n-1} \end{bmatrix} \begin{bmatrix} a_0 \\ a_1 \\ \vdots \\ a_n-1 \end{bmatrix} =\begin{bmatrix} y_0 \\ y_1 \\ \vdots \\ y_n-1 \end{bmatrix} ⎣ ⎡11⋮1x0x1⋮xn−1⋯⋯⋱⋯x0n−1x1n−1⋮xn−1n−1⎦ ⎤⎣ ⎡a0a1⋮an−1⎦ ⎤=⎣ ⎡

本文详细介绍了快速傅里叶变换(FFT)算法,包括多项式加法、乘法、系数表示和点值表示。重点讨论了DFT与FFT的概念,阐述了单位复数根的性质,以及FFT的分治策略和时间复杂度。此外,还提供了FFT的代码实现,并举例说明其在高精度乘法中的应用。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



