文章目录
1.多项式运算
设 A ( x ) = a 0 + a 1 x + a 2 x 2 + ⋯ + a n − 1 x n − 1 B ( x ) = b 0 + b 1 x + b 2 x 2 + ⋯ + b n − 1 x n − 1 设A(x) = a_0+a_1x+a_2x^2+\dots+a_{n-1}x^{n-1}\\ B(x) = b_0+b_1x+b_2x^2+\dots+b_{n-1}x^{n-1}\\ 设A(x)=a0+a1x+a2x2+⋯+an−1xn−1B(x)=b0+b1x+b2x2+⋯+bn−1xn−1
-
加法
A ( x ) + B ( x ) = ( a 0 + b 0 ) + ( a 1 + b 1 ) x + ⋯ + ( a n − 1 + b n − 1 ) x x − 1 A(x)+B(x) = \\(a_0+b_0)+(a_1+b_1)x+\dots+(a_{n-1}+b{n-1})x^{x-1} A(x)+B(x)=(a0+b0)+(a1+b1)x+⋯+(an−1+bn−1)xx−1 -
求值
-
普通算法 复杂度为 O ( n 2 ) O(n^2) O(n2)
-
霍尔算法(秦九韶算法) 复杂度为 O ( n ) O(n) O(n)
A 1 ( x ) = a n − 1 A 2 ( x ) = a n − 2 + x A 1 ( x ) = a n − 2 + a n − 1 x A 3 ( x ) = a n − 3 + x A 3 ( x ) = a n − 3 + a n − 2 x + a n − 2 x 2 … A n ( x ) = a 0 + x A n − 1 ( x ) = A ( x ) A_1(x) = a_{n-1}\\ A_2(x) = a_{n-2}+xA_1(x) = a_{n-2}+a_{n-1}x\\ A_3(x) = a_{n-3}+xA_3(x) = a_{n-3}+a_{n-2}x+a_{n-2}x^2\\ \dots\\ A_n(x) = a_0+xA_{n-1}(x) =A(x) A1(x)=an−1A2(x)=an−2+xA1(x)=an−2+an−1xA3(x)=an−3+xA3(x)=an−3+an−2x+an−2x2…An(x)=a0+xAn−1(x)=A(x)
-
-
乘法
C ( x ) = A ( x ) B ( x ) = ∑ k = 0 m + n − 2 c k x k 其中 c k = ∑ i + j = k a i b j C(x) = A(x)B(x) = \sum_{k=0}^{m+n-2}c_kx^k\\ 其中c_k = \sum_{i+j=k}a_ib_j\\ C(x)=A(x)B(x)=k=0∑m+n−2ckxk其中ck=i+j=k∑aibj
蛮力算法为 O ( n 2 ) O(n^2) O(n2)(以乘法为基本操作)用图形表示如下,在下述矩阵中,每个斜线的和恰好是乘法中的各个分量。
2.多项式的点值表示法
-
引理
一个系数在复数域上的 n − 1 度的多项式有 n 个复数根 一个系数在复数域上的n-1度的多项式有n个复数根 一个系数在复数域上的n−1度的多项式有n个复数根
推论
度数为 n − 1 的多项式 A ( x ) 由 n 个不同的 x 值唯一确定。 即 : n 个点确定一个 n − 1 次幂的多项式 度数为n-1的多项式A (x)由n个不同的x值唯一确定。\\ 即:n个点确定一个n-1次幂的多项式 度数为n−1的多项式A(x)由n个不同的x值唯一确定。即:n个点确定一个n−1次幂的多项式 -
点值表示法
A ( x ) = ( x 0 , y 0 ) , … , ( x n − 1 , y n − 1 ) B ( x ) = ( x 0 , z 0 ) , … , ( x n − 1 , z n − 1 ) A(x) = (x_0,y_0),\dots,(x_{n-1},y_{n-1})\\ B(x) = (x_0,z_0),\dots,(x_{n-1},z_{n-1})\\ A(x)=(x0,y0),…,(xn−1,yn−1)B(x)=(x0,z0),…,(xn−1,zn−1) -
点值表示法中的加法
A ( x ) + B ( x ) : ( x 0 , y 0 + z 0 ) , … , ( x n − 1 , y n − 1 + z n − 1 ) A(x)+B(x) :(x_0,y_0+z_0),\dots,(x_{n-1},y_{n-1}+z_{n-1}) A(x)+B(x):(x0,y0+z0),…,(xn−1,yn−1+zn−1) -
点值表示法中的求值
A ( x ) = ∑ k = 0 n − 1 y k ∏ j ≠ k ( x − x j ) ∏ j ≠ k ( x k − x j ) ( L a g r a n g e f o r m u l a ) A(x) = \sum_{k=0}^{n-1} y_k\frac{\prod_{j\neq k}(x-x_j)}{\prod_{j\neq k}(x_k-x_j)}(Lagrange formula)\\ A(x)=k=0∑n−1yk∏j=k(xk−xj)∏j=k(x−xj)(Lagrangeformula)
以乘法为基本运算,复杂度为 O ( n 2 ) O(n^2) O(n2) -
点值表示法中的乘法
A ( x ) ∗ B ( x ) : ( x 0 , y 0 ∗ z 0 ) , … , ( x n − 1 , y n − 1 ∗ z n − 1 ) A(x)*B(x):(x_0,y_0*z_0),\dots,(x_{n-1},y_{n-1}*z_{n-1}) A(x)∗B(x):(x0,y0∗z0),…,(xn−1,yn−1∗zn−1)
在点值表示法中,若以乘法为基本运算,则复杂度为 O ( n ) O(n) O(n),但是需要2n-1个点
3.粗略的系数表示和点值表示的转换
我们既想要快速的求值(O(n)),又想要快速的乘法(O(n))。能否在两种表示方法之间快速转换,借此满足要求。
-
从系数表示到点值表示
-
从点值表示到系数表示 复杂度为 O ( n 3 ) O(n^3) O(n3)
4.从系数表示到点表示(利用分治算法求n个点的取值)
我们强调,利用分治算法不是为了在单个点上提高效率,单个点上霍尔算法已经最优,而是为了在n个点时提高效率。
-
两种划分子问题方法
-
减少复杂度的方法
简而易见,如果依然计算n个点,那么求值的复杂度不会有任何提高。如果能用n/2点代替n个点呢
设 n 个点为 ± x 0 , … , ± x n − 1 则 A ( x i ) = A e v e n ( x i 2 ) + x i A o d d ( x i 2 ) A ( − x i ) = A e v e n ( x i 2 ) − x i A o d d ( x i 2 ) 设n个点为\pm x_0,\dots,\pm x_n-1\\ 则A(x_i) = A_{even}(x_i^2)+x_iA_{odd}(x_i^2)\\ A(-x_i)= A_{even}(x_i^2)-x_iA_{odd}(x_i^2) 设n个点为±x0,…,±xn−1则A(xi)=Aeven(xi2)+xiAodd(xi2)A(−xi)=Aeven(xi2)−xiAodd(xi2)
现在只需要计算n/2个点的 A e v e n ( x i 2 ) 、 A o d d ( x i 2 ) A_{even}(x_i^2)、A_{odd}(x_i^2) Aeven(xi2)、Aodd(xi2)即可。
但是, x 2 x^2 x2相等的技巧只在递归树的最顶层有效,无法形成递归。怎么样使得 x 0 2 , x 1 2 , x 2 2 . . x_0^2,x_1^2,x_2^2.. x02,x12,x22..也互为相反数呢?
毫无疑问,我们需要复数。我们可以从底向上缔造满足条件的一个树,如下图
我们可以发现,第n层节点满足 x n = 1 x^n=1 xn=1。可以借助下面的定理来求解x的值
若 ω n = 1 , 则 ω = e 2 π i / n = c o s 2 π n + i s i n 2 π n 推论 1 :若 n 为偶数,那么 n 个根互为相反数,即 ω n 2 + j = − ω j 推论 2 : 将 n 平方,产生 n / 2 个根,即 w 2 = e 4 π i / n = { v 0 , … , v n / 2 − 1 } 推论 3 : ω 1 0 = ω 0 , ω 1 k = ω k 若\omega^n=1,则\omega = e^{2\pi i/n} = cos\frac {2\pi}n+isin\frac{2\pi}n\\ 推论1:若n为偶数,那么n个根互为相反数,即\omega ^{\frac n2+j} = -\omega^{j}\\ 推论2:将n平方,产生n/2个根,即w^2 = e^{4\pi i/n} = \{v^0,\dots,v^{n/2-1}\}\\ 推论3:\omega_1^0 = \omega_0,\omega_1^k = \omega_k 若ωn=1,则ω=e2πi/n=cosn2π+isinn2π推论1:若n为偶数,那么n个根互为相反数,即ω2n+j=−ωj推论2:将n平方,产生n/2个根,即w2=e4πi/n={v0,…,vn/2−1}推论3:ω10=ω0,ω1k=ωk
若 n = 2 k n=2^k n=2k,那么在递归的第i层,我们有 n / 2 i n/2^i n/2i个节点,由于 n / 2 i n/2^i n/2i恒为偶数,由上述"推论1"可知,这 n / 2 i n/2^i n/2i个节点互为相反数。以n=8为例,8个根的分布如下图。
因此,若 n = 2 k n=2^k n=2k,在递归树的每一层,节点之间两两都互为相反数。递归得以进行。
那么有
T ( n ) = T ( n 2 ) + O ( n ) T ( n ) = Θ ( n log n ) T(n) = T(\frac n2)+O(n)\\ T(n) = \Theta(n\log n) T(n)=T(2n)+O(n)T(n)=Θ(nlogn)
至此,我们将求n个点的值的复杂度从 O ( n 2 ) O(n^2) O(n2)降到了 O ( n log n ) O(n\log n) O(nlogn)
5.FFT伪代码
思路如“4”中所说
-
算法:FFT(A,n, ω \omega ω)
-
输入:n为2的幂。n-1阶多项式A,n个根 ω i \omega^i ωi,其中 ω i = e 2 π i / n \omega^i = e^{2\pi i/n} ωi=e2πi/n
-
输出: A ( ω i ) , i ∈ [ 0 , n − 1 ] A(\omega ^i),i\in[0,n-1] A(ωi),i∈[0,n−1]
-
伪代码
1. if n=1 then return a_0 2.express A(x) = A_even(x^2)+x*A_odd(x^2) 3.FFT(A_even,n/2,w^2) 4.FFT(A_odd,n/2,w^2) 5.for j=0 to n-1 do 6. A(w^j) = A_even(w^2j)+w_j*A_odd(w^2j) 7.return A(w^0)..A(w^n-1)
-
复杂度如‘4’中的分析
有了FFT算法,我们可以以 Θ ( n log n ) \Theta(n\log n) Θ(nlogn)的复杂度将多项式的系数表示法转换为点表示法。
6.从点表示到系数表示(逆FFT)
-
傅里叶矩阵
-
正向矩阵
如下图, a i a_i ai代表多项式的系数。利用该矩阵,可以求出n个( ω i , y i \omega _i,y_i ωi,yi)点对。(DFT算法)
-
逆矩阵
给定n个点对,通过下述矩阵可以求出多项式的系数
-
解逆矩阵
将傅里叶逆矩阵化为 F n ( ω ) F_n(\omega) Fn(ω)的形式(根据“4”中的推论3得出),并求出 F n ( ω ) F_n(\omega) Fn(ω)的逆,如下图
我们有 1 n F n ( ω − 1 ) = F n ( ω ) − 1 \frac 1n F_n(\omega^{-1}) =F_n(\omega)^{-1} n1Fn(ω−1)=Fn(ω)−1。其中 w − 1 = e − 2 π i / n w^{-1} = e^{-2\pi i/n} w−1=e−2πi/n
因此
-
-
逆FFT算法
若按照上述矩阵计算,那么复杂度仍为 O ( n 2 ) O(n^2) O(n2),因此,依然需要用到FFT。只需将 ω \omega ω换成 − ω -\omega −ω,将 a i a_i ai的位置和 y i y_i yi的位置互换,即为逆FTT。可以用逆FFT实现从点表示到系数表示的转换,复杂度为 Θ ( n log n ) \Theta(n\log n) Θ(nlogn)
PS:因为 n = 2 k n=2^k n=2k,故n个根之间互为相反数。因此将 ω \omega ω换成 − ω -\omega −ω之后,依然可以调用分治算法计算。
7.多项式乘法
8.多项式乘法的应用与扩展
- 应用:可以应用在整数乘法中,可以将两个乘数转换为二进制多项式的形式(令x = 2,系数为0或1),即可利用FFT计算乘法
- 扩展:FFT是在复数域上的运算,精度难免会有损失,有时我们需要在有限域上计算。那么当n|p-1时, ω n = 1 m o d p \omega ^n=1modp ωn=1modp有n个根。NTT算法:通过将离散傅里叶专门化到有限域F中得到。