基于 Newton Iteration 的多项式快速除法
传统的多项式的带余除法 (Synthetic Division) 需要 O ( n 2 ) O(n^2) O ( n 2 ) 的计算复杂度。本节介绍一种利用 Newton Iteration 的快速除法算法,算法复杂度与多项式乘法一致,仅为 O ( M ( n ) ) O(M(n)) O ( M ( n )) 。其中 M ( n ) M(n) M ( n ) 表示多项式乘法的复杂度。
逆序多项式 ¶ 假设一个有限域 F F F ,对于 F [ X ] F[X] F [ X ] 上的多项式 f ( X ) f(X) f ( X ) 与 g ( X ) g(X) g ( X ) ,因为 F [ X ] F[X] F [ X ] 是一个 Euclidian Domain,所以 f ( X ) f(X) f ( X ) 与 g ( X ) g(X) g ( X ) 满足下面的带余除法等式:
f ( X ) = g ( X ) ⋅ q ( X ) + r ( X ) f(X) = g(X)\cdot q(X) + r(X) f ( X ) = g ( X ) ⋅ q ( X ) + r ( X ) 并且 deg ( r ) < deg ( g ) \deg(r)<\deg(g) deg ( r ) < deg ( g ) 。为了方便后续的描述,我们记 n = deg ( f ) n=\deg(f) n = deg ( f ) ,m = deg ( g ) m=\deg(g) m = deg ( g ) 。
下面我们先介绍一个重要的概念,逆序多项式 。假如 f ( X ) f(X) f ( X ) 表示为如下的系数形式:
f = a 0 + a 1 X + ⋯ + a n − 1 X n − 1 ∈ F [ X ] f = a_0 + a_1X + \cdots + a_{n-1}X^{n-1} \in F[X] f = a 0 + a 1 X + ⋯ + a n − 1 X n − 1 ∈ F [ X ] 那么它的逆序多项式为:
r e v ( f ) = a n − 1 + a n − 2 X + ⋯ + a 1 X n − 2 + a 0 X n − 1 ∈ F [ X ] \mathsf{rev}(f) = a_{n-1} + a_{n-2}X + \cdots + a_1X^{n-2} + a_0X^{n-1} \in F[X] rev ( f ) = a n − 1 + a n − 2 X + ⋯ + a 1 X n − 2 + a 0 X n − 1 ∈ F [ X ] 简单来说,r e v ( f ) \mathsf{rev}(f) rev ( f ) 就是把 f f f 的系数按顺序倒转,原多项式最高次项系数作为逆序多项式的常数项,次高项系数作为逆序多项式的 X X X 项系数,依此类推。下面我们给出逆序变换的定义:r e v k ( f ) : F [ X ] → F [ X ] \mathsf{rev}_k(f):F[X]\to F[X] rev k ( f ) : F [ X ] → F [ X ] :
r e v k ( f ) : f ⟼ X k f ( 1 X ) \mathsf{rev}_k(f): f \longmapsto X^kf\left(\frac{1}{X}\right) rev k ( f ) : f ⟼ X k f ( X 1 ) 如果 k = deg ( f ) k=\deg(f) k = deg ( f ) ,那么 r e v k ( f ) \mathsf{rev}_k(f) rev k ( f ) 就表示 f f f 的逆序多项式,我们可以用省略下标 k k k ,写为 r e v ( f ) \mathsf{rev}(f) rev ( f ) 。下面展开下 r e v k ( f ) \mathsf{rev}_k(f) rev k ( f ) 的定义:
r e v k ( f ) = X k f ( 1 X ) = X k ( a 0 + a 1 X + ⋯ + a n − 2 X n − 2 + a n − 1 X n − 1 ) = a 0 X k + a 1 X k − 1 + ⋯ + a n − 1 X k − n + 1 = X k − n + 1 ( a n − 1 + a n − 2 X + ⋯ + a 1 X n − 2 + a 0 X n − 1 ) \begin{aligned}
\mathsf{rev}_k(f) & = X^kf\left(\frac{1}{X}\right) \\
& = X^k\left(a_0 + \frac{a_{1}}{X} + \cdots + \frac{a_{n-2}}{X^{n-2}} + \frac{a_{n-1}}{X^{n-1}}\right) \\
& = a_0X^k + a_1X^{k-1} + \cdots + a_{n-1}X^{k-n+1} \\
& = X^{k-n+1}\big( a_{n-1} + a_{n-2}X + \cdots + a_1X^{n-2} + a_0X^{n-1} \big)
\end{aligned} rev k ( f ) = X k f ( X 1 ) = X k ( a 0 + X a 1 + ⋯ + X n − 2 a n − 2 + X n − 1 a n − 1 ) = a 0 X k + a 1 X k − 1 + ⋯ + a n − 1 X k − n + 1 = X k − n + 1 ( a n − 1 + a n − 2 X + ⋯ + a 1 X n − 2 + a 0 X n − 1 ) 其中 k ≥ ( n − 1 ) k\ge (n-1) k ≥ ( n − 1 ) 。 如果 k = n − 1 k=n-1 k = n − 1 ,那么 r e v k ( f ) \mathsf{rev}_k(f) rev k ( f ) 正好等于 f f f 的逆序多项式。容易验证,r e v k \mathsf{rev}_k rev k 满足加法同态:
r e v k ( f + g ) = r e v k ( f ) + r e v k ( g ) \mathsf{rev}_k(f+g) = \mathsf{rev}_k(f) + \mathsf{rev}_k(g) rev k ( f + g ) = rev k ( f ) + rev k ( g ) 并且 r e v k \mathsf{rev}_k rev k 也满足下面的乘法关系:
r e v k ( f ⋅ g ) = r e v j ( f ) ⋅ r e v k − j ( g ) \mathsf{rev}_k(f\cdot g) = \mathsf{rev}_j(f)\cdot \mathsf{rev}_{k-j}(g) rev k ( f ⋅ g ) = rev j ( f ) ⋅ rev k − j ( g ) r e v k ( f ) = X d ⋅ r e v k − d ( f ) \mathsf{rev}_k(f) = X^d \cdot \mathsf{rev}_{k-d}(f) rev k ( f ) = X d ⋅ rev k − d ( f ) 我们把 f ( X ) f(X) f ( X ) 的除法分解的等式代入 r e v ( f ) \mathsf{rev}(f) rev ( f ) 的定义,可得:
r e v n − 1 ( f ) = r e v n − 1 ( p ⋅ g + r ) = r e v n − 1 ( p ⋅ g ) + r e v n − 1 ( r ) = r e v n − m ( q ) ⋅ r e v m − 1 ( g ) + X n − m + 1 r e v m − 2 ( r ) \begin{aligned}
\mathsf{rev}_{n-1}(f) & = \mathsf{rev}_{n-1}(p\cdot g + r) \\
& = \mathsf{rev}_{n-1}(p\cdot g) + \mathsf{rev}_{n-1}(r) \\
& = \mathsf{rev}_{n-m}(q)\cdot \mathsf{rev}_{m-1}(g) + X^{n-m+1}\mathsf{rev}_{m-2}(r)
\end{aligned} rev n − 1 ( f ) = rev n − 1 ( p ⋅ g + r ) = rev n − 1 ( p ⋅ g ) + rev n − 1 ( r ) = rev n − m ( q ) ⋅ rev m − 1 ( g ) + X n − m + 1 rev m − 2 ( r ) 然后我们可以得到下面的等式:
r e v ( f ) ≡ r e v n − m ( q ) ⋅ r e v m − 1 ( g ) m o d X n − m + 1 \mathsf{rev}(f) \equiv \mathsf{rev}_{n-m}(q)\cdot \mathsf{rev}_{m-1}(g) \mod{X^{n-m+1}} rev ( f ) ≡ rev n − m ( q ) ⋅ rev m − 1 ( g ) mod X n − m + 1 注意到,上面的等式中 r ( X ) r(X) r ( X ) 被 X n − m + 1 X^{n-m+1} X n − m + 1 提升变成了高次项,因此我们可以通过多项式模运算抹掉。
这么做的目的是,多项式的除法运算不再需要考虑余数多项式 r ( X ) r(X) r ( X ) ,我们只要通过上面的等式来计算商多项式 q ( X ) q(X) q ( X ) 的逆序多项式 r e v ( q ) \mathsf{rev}(q) rev ( q ) 即可。
然后我们再对上面等式进行变换,得到 r e v n − m ( q ) \mathsf{rev}_{n-m}(q) rev n − m ( q ) 的计算式:
r e v n − m ( q ) ≡ r e v n − 1 ( f ) ⋅ r e v m − 1 ( g ) − 1 m o d X n − m + 1 \mathsf{rev}_{n-m}(q) \equiv \mathsf{rev}_{n-1}(f)\cdot \mathsf{rev}_{m-1}(g)^{-1} \mod{X^{n-m+1}} rev n − m ( q ) ≡ rev n − 1 ( f ) ⋅ rev m − 1 ( g ) − 1 mod X n − m + 1 计算商多项式 q ( X ) q(X) q ( X ) 则进一步依赖一个模运算下的多项式求逆运算,即如何计算 r e v m − 1 ( g ) − 1 \mathsf{rev}_{m-1}(g)^{-1} rev m − 1 ( g ) − 1 ,使得 r e v m − 1 ( g ) ⋅ r e v m − 1 ( g ) − 1 ≡ 1 m o d X n − m + 1 \mathsf{rev}_{m-1}(g)\cdot \mathsf{rev}_{m-1}(g)^{-1} \equiv 1\mod{X^{n-m+1}} rev m − 1 ( g ) ⋅ rev m − 1 ( g ) − 1 ≡ 1 mod X n − m + 1 。为了方便起见,我们引入一个新的常数变量:l = n − m + 1 l=n-m+1 l = n − m + 1 。注意到 因为 l > n − m = deg ( q ) l>n-m=\deg(q) l > n − m = deg ( q ) ,所以
r e v n − m ( q ) = r e v n − m ( f ) ⋅ r e v m − 1 ( g ) − 1 \mathsf{rev}_{n-m}(q) = \mathsf{rev}_{n-m}(f)\cdot \mathsf{rev}_{m-1}(g)^{-1} rev n − m ( q ) = rev n − m ( f ) ⋅ rev m − 1 ( g ) − 1 如果我们能顺利计算出 r e v n − m ( q ) \mathsf{rev}_{n-m}(q) rev n − m ( q ) ,那么 q ( X ) q(X) q ( X ) 就可以求解出:
q = r e v n − m ( r e v n − m ( q ) ) q = \mathsf{rev}_{n-m}(\mathsf{rev}_{n-m}(q)) q = rev n − m ( rev n − m ( q )) 接下来一个疑问是,在带有模运算的多项式等式中,计算一个多项式的乘法逆(Multiplicative Inverse)会更容易计算吗?换句话说,我们如何计算商环 F [ X ] / ⟨ X l ⟩ F[X]/\langle X^l \rangle F [ X ] / ⟨ X l ⟩ 中的乘法逆?
商环中乘法逆元的存在性 ¶ 我们知道环中只有 Unit Element 才有乘法逆元,那么对于商环 F [ X ] / ⟨ X l ⟩ F[X]/\langle X^l \rangle F [ X ] / ⟨ X l ⟩ 中的元素,哪些多项式才存在乘法逆元?因为 X l X^l X l 显然并不是一个 Irreducible Polynomial,所以 F [ X ] / ⟨ X l ⟩ F[X]/\langle X^l \rangle F [ X ] / ⟨ X l ⟩ 并不构成一个 Field。
进而我们可以考虑 F [ X ] F[X] F [ X ] 的子环 F [ X ] / ⟨ X l ⟩ F[X]/\langle X^l \rangle F [ X ] / ⟨ X l ⟩ ,其中任何一个多项式 f ( X ) f(X) f ( X ) 是否都存在一个 Inverse Element?答案是 Yes。这是因为
对于任何一个 Euclidean Domain R R R ,如果其中两个元素 a , m ∈ R a, m\in R a , m ∈ R ,它们互素,即 gcd ( a , m ) = 1 \gcd(a, m)=1 g cd( a , m ) = 1 ,那么通过 Extended Euclidean Algorithm 可以计算得到 s , t ∈ R s, t\in R s , t ∈ R ,
它们满足下面的 Bezout 等式:
s a + t m = 1 s a + t m = 1 s a + t m = 1 而对于任何一个模 X l X^l X l 的多项式 f ∈ F [ X ] / ⟨ X l ⟩ f\in F[X]/\langle X^l \rangle f ∈ F [ X ] / ⟨ X l ⟩ ,只要它的常数项不为零,那么 gcd ( f , X l ) = 1 \gcd(f, X^l)=1 g cd( f , X l ) = 1 ,满足上面的性质,所以我们可以通过 Extended Euclidean Algorithm 计算得到 f m o d X l f\bmod{X^l} f mod X l 的 Inverse,不过这需要 O ( n 2 ) O(n^2) O ( n 2 ) 的复杂度。
而对于我们要解决的问题,计算 g ⋅ h ≡ 1 m o d X l g\cdot h \equiv 1\mod{X^l} g ⋅ h ≡ 1 mod X l 中的 h h h 来说,因为 g g g 为某个多项式的逆序多项式,所以它的常数项一定不为零,特别是如果原多项式为 Monic (首项为一)多项式,那么它的常数项为 1,即 g ( 0 ) = 1 g(0)=1 g ( 0 ) = 1 。
我们当然可以采用上面的递推式来计算 h h h 的近似解,即计算 ( b 0 , b 1 , ⋯ , b l − 1 ) (b_0, b_1, \cdots, b_{l-1}) ( b 0 , b 1 , ⋯ , b l − 1 ) 的系数,不过这需要 O ( l 2 ) O(l^2) O ( l 2 ) 的复杂度。
幂级数环与多项式求逆 ¶ 为了计算多项式的求逆,我们需要介绍一个重要概念,形式幂级数环(Formal Power Series Ring)。对于多项式环 F [ X ] F[X] F [ X ] 中的多项式,如果我们对其扩充,对任意的多项式都加上具有无限非零高次项,那么我们就可以得到一个形式幂级数环 F [ [ X ] ] F[[X]] F [[ X ]] :
p ( X ) = ∑ i = 0 ∞ a i X i ∈ F [ [ X ] ] p(X) = \sum_{i=0}^{\infty} a_iX^i \in F[[X]] p ( X ) = i = 0 ∑ ∞ a i X i ∈ F [[ X ]] 对于任意的 p 1 , p 2 ∈ F [ [ X ] ] p_1, p_2\in F[[X]] p 1 , p 2 ∈ F [[ X ]] ,环的加法和乘法定义如下:
p 1 ( X ) + p 2 ( X ) = ∑ i = 0 ∞ ( a i + b i ) X i p_1(X) + p_2(X) = \sum_{i=0}^{\infty}(a_i + b_i)X^i p 1 ( X ) + p 2 ( X ) = i = 0 ∑ ∞ ( a i + b i ) X i p 1 ( X ) ⋅ p 2 ( X ) = ∑ i = 0 ∞ ( ∑ j = 0 i a j b i − j ) X i p_1(X)\cdot p_2(X) = \sum_{i=0}^{\infty}\Big(\sum_{j=0}^{i}a_j b_{i-j}\Big)X^i p 1 ( X ) ⋅ p 2 ( X ) = i = 0 ∑ ∞ ( j = 0 ∑ i a j b i − j ) X i 另外任何一个非零的 p ( X ) p(X) p ( X ) 都可以唯一地分解为 X n p 0 ( X ) X^n p_0(X) X n p 0 ( X ) ,其中 p 0 ( X ) p_0(X) p 0 ( X ) 的常数项非零。F [ [ X ] ] F[[X]] F [[ X ]] 是一个 UFD,即唯一分解环。定义函数 δ ( p ) = n \delta(p) = n δ ( p ) = n ,那么 F [ [ X ] ] F[[X]] F [[ X ]] 是一个 Euclidean Domain。
而对于多项式环中的任意多项式 f ( X ) ∈ F [ X ] f(X)\in F[X] f ( X ) ∈ F [ X ] ,我们可以把它看成高次项系数为零的幂级数,即
f ( X ) = ∑ i = 0 d a i X i + ∑ i = d + 1 ∞ 0 X i f(X) = \sum_{i=0}^{d}a_iX^i + \sum_{i=d+1}^{\infty}0X^i f ( X ) = i = 0 ∑ d a i X i + i = d + 1 ∑ ∞ 0 X i 我们也可以通过多项式的模运算,把任何一个幂级数 p ( X ) p(X) p ( X ) 映射到 F [ X ] F[X] F [ X ] 中的多项式,即
p ( X ) = ∑ i = 0 d a i X i + O ( X d + 1 ) ≡ f ( X ) m o d X d p(X) = \sum_{i=0}^{d}a_iX^i + O(X^{d+1}) \equiv f(X) \mod{X^d} p ( X ) = i = 0 ∑ d a i X i + O ( X d + 1 ) ≡ f ( X ) mod X d 这里 O ( X d + 1 ) O(X^{d+1}) O ( X d + 1 ) 表示的是所有 X d + 1 X^{d+1} X d + 1 及更高次项的项,通过把高于 X d X^d X d 的项标记为不关心的尾项,我们就可以得到幂级数 p ( X ) p(X) p ( X ) 的近似表示,其中 d d d 表示近似的精度。
因此我们可以得到结论,F [ X ] F[X] F [ X ] 是 F [ [ X ] ] F[[X]] F [[ X ]] 的子环,我们可以通过一个单同态映射将 F [ X ] F[X] F [ X ] 中的元素嵌入到 F [ [ X ] ] F[[X]] F [[ X ]] 中:
ι : F [ X ] → F [ [ X ] ] f ( X ) ↦ ∑ i = 0 d a i X i + ∑ i = d + 1 ∞ 0 X i \begin{aligned}
\iota: & F[X] \to F[[X]] \\
& f(X) \mapsto \sum_{i=0}^{d}a_iX^i + \sum_{i=d+1}^{\infty}0X^i
\end{aligned} ι : F [ X ] → F [[ X ]] f ( X ) ↦ i = 0 ∑ d a i X i + i = d + 1 ∑ ∞ 0 X i 为何我们要引入幂级数环?因为幂级数环还有一个非常有用的性质 :
任何一个常数项非零的幂级数 p ( X ) p(X) p ( X ) 都存在一个乘法逆元 p ~ ( X ) \tilde{p}(X) p ~ ( X ) ,使得 p ( X ) ⋅ p ~ ( X ) = 1 p(X)\cdot \tilde{p}(X) = 1 p ( X ) ⋅ p ~ ( X ) = 1 这个结论看起来有点神奇,我们先看一个简单的例子:
p 1 ( X ) ∈ F 7 [ X ] = 1 + 2 X + 3 X 2 + 2 X 3 p_1(X)\in \mathbb{F}_7[X] = 1 + 2X + 3X^2 + 2X^3 p 1 ( X ) ∈ F 7 [ X ] = 1 + 2 X + 3 X 2 + 2 X 3 那么它的乘法逆元素为一个可能无限长的幂级数。为了方便表示,我们仅取其前十项,即精度为 10:
p ~ 1 ( X ) = 1 + 5 X + X 2 + 2 X 3 + 4 X 4 + 5 X 5 + 2 X 6 + X 7 + 3 X 8 + X 9 + O ( X 10 ) \tilde{p}_1(X) = 1 + 5X + X^2 + 2X^3 + 4X^4 + 5X^5 + 2X^6 + X^7 + 3X^8 + X^9 + O(X^{10}) p ~ 1 ( X ) = 1 + 5 X + X 2 + 2 X 3 + 4 X 4 + 5 X 5 + 2 X 6 + X 7 + 3 X 8 + X 9 + O ( X 10 ) 而它的尾项 O ( X 10 ) O(X^{10}) O ( X 10 ) 则表示的是所有 X 10 X^{10} X 10 之后的项的总和。
我们可以试着再将去掉尾项的 p ~ 1 ( X ) \tilde{p}_1(X) p ~ 1 ( X ) 作为一个多项式,把它乘以 p 1 ( X ) p_1(X) p 1 ( X ) ,看看运算结果是什么:
p 1 ( X ) ⋅ ( 1 + 5 X + X 2 + 2 X 3 + 4 X 4 + 5 X 5 + 2 X 6 + X 7 + 3 X 8 + X 9 ) ) = 1 + 6 X 10 + 2 X 11 + 2 X 12 \begin{aligned}
& p_1(X)\cdot (1 + 5X + X^2 + 2X^3 + 4X^4 + 5X^5 + 2X^6 + X^7 + 3X^8 + X^9)) \\
= & 1 + 6X^{10} + 2X^{11} + 2X^{12}
\end{aligned} = p 1 ( X ) ⋅ ( 1 + 5 X + X 2 + 2 X 3 + 4 X 4 + 5 X 5 + 2 X 6 + X 7 + 3 X 8 + X 9 )) 1 + 6 X 10 + 2 X 11 + 2 X 12 我们得到了一个近似等于 1 的多项式。乘积结果的尾巴上只带有未知数次数大于等于 10 的项。换句话说,如何考虑精度为 10,那么这个乘积结果正是约等于 1。
如果我们如何计算这个可能无限长的 p ~ ( X ) \tilde{p}(X) p ~ ( X ) 呢?下面我们推导下计算公式。
假设
p ~ ( X ) = ∑ i = 0 ∞ b i X i \tilde{p}(X)=\sum_{i=0}^{\infty}b_iX^i p ~ ( X ) = i = 0 ∑ ∞ b i X i 那么显然下面的公式成立:
( ∑ i = 0 ∞ b i X i ) ( ∑ i = 0 ∞ a i X i ) = 1 \Big(\sum_{i=0}^{\infty}b_iX^i\Big)\Big(\sum_{i=0}^{\infty}a_iX^i\Big) = 1 ( i = 0 ∑ ∞ b i X i ) ( i = 0 ∑ ∞ a i X i ) = 1 因为 a 0 ≠ 0 a_0\neq 0 a 0 = 0 ,那么 b 0 = 1 a 0 b_0 = \frac{1}{a_0} b 0 = a 0 1 ,这是因为 a 0 b 0 = 1 a_0b_0 = 1 a 0 b 0 = 1 。然后我们再考虑乘积的一次项,
因为 X X X 项的系数为零,所以
a 1 b 0 + a 0 b 1 = 0 a_1b_0 + a_0b_1 = 0 a 1 b 0 + a 0 b 1 = 0 所以我们可以得到
b 1 = − a 1 b 0 a 0 b_1 = -\frac{a_1b_0}{a_0} b 1 = − a 0 a 1 b 0 通过类似的推导,我们可以得到 b 2 b_2 b 2 的表达式:
b 2 = − a 1 b 1 + a 2 b 0 a 0 b_2 = -\frac{a_1b_1 + a_2b_0}{a_0} b 2 = − a 0 a 1 b 1 + a 2 b 0 这个规律可以推广到任意 b k b_k b k ,得到一个递推计算公式:
b k = − a 1 b k − 1 + a 2 b k − 2 + ⋯ a k b 0 a 0 = − 1 a 0 ( ∑ j = 1 k a j b k − j ) b_k = -\frac{a_1b_{k-1} + a_2b_{k-2} + \cdots a_kb_0 }{a_0} = -\frac{1}{a_0}\Big(\sum_{j=1}^{k}a_{j}b_{k-j}\Big) b k = − a 0 a 1 b k − 1 + a 2 b k − 2 + ⋯ a k b 0 = − a 0 1 ( j = 1 ∑ k a j b k − j ) 这个递推式可以一直持续下去,依次从 p ~ ( X ) \tilde{p}(X) p ~ ( X ) 的低次项系数计算到高次项系数,直到达到所要求的计算精度为止。
形式幂级数环 F [ [ X ] ] F[[X]] F [[ X ]] 实际上是一个局部环(Local Ring),即它只有一个极大理想 ⟨ X ⟩ \langle X \rangle ⟨ X ⟩ 。所有这个极大理想之外的幂级数(常数项非零的元素)都是 Unit Elements,即存在乘法逆元。
回到我们的问题,已知一个多项式 g ∈ F [ X ] g\in F[X] g ∈ F [ X ] ,我们需要求解它的乘法逆元 h ∈ F [ X ] h\in F[X] h ∈ F [ X ] 满足 g ⋅ h ≡ 1 m o d X l g\cdot h \equiv 1 \mod{X^l} g ⋅ h ≡ 1 mod X l 。又因为这个多项式 g g g 是某个多项式的逆序多项式,那么我们可以肯定它的常数项一定非零。于是,根据上面的算法,我们就可以求出一个 g ~ ∈ F [ [ X ] ] \tilde{g}\in F[[X]] g ~ ∈ F [[ X ]] 满足 g ~ ⋅ g = 1 \tilde{g}\cdot g = 1 g ~ ⋅ g = 1 。当然,我们不需要求出 g ~ \tilde{g} g ~ 的精确结果,因为 g ~ \tilde{g} g ~ 是一个无限长的幂级数,我们只需要求出它的近似解即可,近似精度只需要大于 X l X^l X l 即可停止递推计算。
h ( X ) = b 0 + b 1 X + b 2 X 2 + ⋯ + b l − 1 X l − 1 h(X) = b_0 + b_1X + b_2X^2 + \cdots + b_{l-1}X^{l-1} h ( X ) = b 0 + b 1 X + b 2 X 2 + ⋯ + b l − 1 X l − 1 到这里,我们已经有了一个多项式除法的算法,但是这个算法的复杂度是 O ( l 2 ) O(l^2) O ( l 2 ) ,
下面我们介绍如何采用牛顿迭代法(Newton Iteration)来计算多项式的乘法逆元,算法复杂度为 O ( M ( l ) ) O(M(l)) O ( M ( l )) ,其中 M ( l ) M(l) M ( l ) 表示多项式乘法的计算量,假如有限域 F F F 为 FFT 友好,那么 O ( M ( l ) ) O(M(l)) O ( M ( l )) 的复杂度为 O ( l log l ) O(l\log l) O ( l log l ) 。
牛顿迭代法 ¶ 牛顿迭代法是数学分析中求解多项式根的一种逐步逼近的迭代算法,比如对于一个实数域上的可导函数 ϕ : R → R \phi: \mathbb{R}\to \mathbb{R} ϕ : R → R ,求解 α \alpha α 满足 ϕ ( α ) = 0 \phi(\alpha)=0 ϕ ( α ) = 0 。首先我们猜测一个初始值 x = α 0 x=\alpha_0 x = α 0 ,然后逐步求解 α 1 , α 2 , ⋯ , α k \alpha_1, \alpha_2, \cdots, \alpha_k α 1 , α 2 , ⋯ , α k ,直至 α k ≅ α \alpha_k\cong\alpha α k ≅ α 。如下图所示,
假设 ϕ ( x ) \phi(x) ϕ ( x ) 在 x = α i x=\alpha_i x = α i 处的切线斜率为 ϕ ′ ( α i ) \phi'(\alpha_i) ϕ ′ ( α i ) ,将切线与 x x x 轴的交点记为 α i + 1 \alpha_{i+1} α i + 1 ,那么它们满足下面的等式:
ϕ ( α i ) α i − α i + 1 = ϕ ′ ( α i ) \frac{\phi(\alpha_i)}{
\alpha_i - \alpha_{i+1}
} = \phi'(\alpha_{i}) α i − α i + 1 ϕ ( α i ) = ϕ ′ ( α i ) 经过简单的公式变换,我们可以得到 α i + 1 \alpha_{i+1} α i + 1 的递推表达式:
α i + 1 = α i − ϕ ( α i ) ϕ ′ ( α i ) \alpha_{i+1} = \alpha_i - \frac{\phi(\alpha_i)}{\phi'(\alpha_i)} α i + 1 = α i − ϕ ′ ( α i ) ϕ ( α i ) 通过反复迭代 k k k 次,我们可以得到一个快速收敛的近似解 α k ≅ α \alpha_k\cong\alpha α k ≅ α 。
同样,如果求解 g ⋅ h ≡ 1 m o d X l g\cdot h \equiv 1 \mod{X^l} g ⋅ h ≡ 1 mod X l ,我们可以仿造上面的实数函数 ϕ ( x ) \phi(x) ϕ ( x ) 构造一个形式幂级数环上的函数 Φ : F [ [ X ] ] → F [ [ X ] ] \Phi: F[[X]] \to F[[X]] Φ : F [[ X ]] → F [[ X ]] ,
Φ ( Y ) = 1 Y − g \Phi(Y) = \frac{1}{Y} - g Φ ( Y ) = Y 1 − g 其导数函数记为 Φ ′ ( Y ) \Phi'(Y) Φ ′ ( Y ) :
Φ ′ ( Y ) = ( 1 Y − g ) ′ = − 1 Y 2 \Phi'(Y) = (\frac{1}{Y} - g)' = -\frac{1}{Y^2} Φ ′ ( Y ) = ( Y 1 − g ) ′ = − Y 2 1 该函数的根 Y = g ~ ∈ F [ [ X ] ] Y = \tilde{g}\in F[[X]] Y = g ~ ∈ F [[ X ]] 将满足 g ~ ⋅ g = 1 \tilde{g}\cdot g = 1 g ~ ⋅ g = 1 :
Φ ( g ~ ) = 1 g ~ − g = g − g = 0 \Phi(\tilde{g}) = \frac{1}{\tilde{g}} - g = g - g = 0 Φ ( g ~ ) = g ~ 1 − g = g − g = 0 请再次注意,因为 g ~ \tilde{g} g ~ 是一个无限多项的幂级数,而我们只需要得到一个近似解 h ≈ g ~ h\approx \tilde{g} h ≈ g ~ ,即
Φ ( h ) = 1 h − g ≈ 0 \Phi(h) = \frac{1}{h} - g \approx 0 Φ ( h ) = h 1 − g ≈ 0 这个精确解 g ~ \tilde{g} g ~ 在 X l X^l X l 或更高次项 X ≤ l X^{\leq l} X ≤ l 的系数不为零,而近似解 h h h 只需要满足低次项系数与 g ~ \tilde{g} g ~ 的低次项系数相同即可:
g ~ = h + O ( X l ) \tilde{g} = h + O(X^l) g ~ = h + O ( X l ) 那么显然 h h h 只需要包含所有低于 X l X^l X l 的项,这样一来,h h h 是多项式环 F [ X ] / ⟨ X l ⟩ F[X]/\langle X^l \rangle F [ X ] / ⟨ X l ⟩ 中的元素:
h = ∑ i = 0 l − 1 b i X i ∈ F [ X ] / ⟨ X l ⟩ h = \sum_{i=0}^{l-1}b_iX^i \quad \in F[X]/\langle X^l \rangle h = i = 0 ∑ l − 1 b i X i ∈ F [ X ] / ⟨ X l ⟩ 并且满足
g ⋅ h = g ⋅ ( g ~ − O ( X l ) ) = 1 − g ⋅ O ( X l ) ≡ 1 m o d X l g\cdot h = g \cdot (\tilde{g} - O(X^l)) = 1 - g\cdot O(X^l) \equiv 1 \mod{X^l} g ⋅ h = g ⋅ ( g ~ − O ( X l )) = 1 − g ⋅ O ( X l ) ≡ 1 mod X l 下面我们尝试用牛顿迭代法来求解 h h h ,其递推公式如下:
h i + 1 = h i − Φ ( h i ) Φ ′ ( h i ) = h i − 1 h i − g − 1 h i 2 = 2 h i − g ⋅ h i 2 h_{i+1} = h_i - \frac{\Phi(h_i)}{\Phi'(h_i)} = h_i - \frac{\frac{1}{h_i} - g}{-\frac{1}{h_i^2}} = 2h_i - g\cdot h_i^2 h i + 1 = h i − Φ ′ ( h i ) Φ ( h i ) = h i − − h i 2 1 h i 1 − g = 2 h i − g ⋅ h i 2 首先我们不妨设 g g g 的常数项为 1,所以 g = 1 + O ( X ) g=1+O(X) g = 1 + O ( X ) 。 然后我们再猜测一个迭代计算的初始值 h 0 = 1 h_0 = 1 h 0 = 1 ,当代入 Y = h 0 Y=h_0 Y = h 0 到 Φ ( Y ) \Phi(Y) Φ ( Y ) 中,
Φ ( h 0 ) = 1 h 0 − g = 1 − g = O ( X ) \Phi(h_0) = \frac{1}{h_0} - g = 1 - g = O(X) Φ ( h 0 ) = h 0 1 − g = 1 − g = O ( X ) 我们可以用 m o d X \bmod{X} mod X 模运算来去除 上面等式右边的尾项 O ( X ) O(X) O ( X ) ,于是可以得到下面的等式:
Φ ( h 0 ) = O ( X ) ≡ 0 m o d X \Phi(h_0) = O(X) \equiv 0 \mod{X} Φ ( h 0 ) = O ( X ) ≡ 0 mod X 上面这个等式可以解读为:h 0 h_0 h 0 是精度 为 X X X 的 Φ ( Y ) \Phi(Y) Φ ( Y ) 函数的近似根。
然后我们利用牛顿迭代递推公式法来进行第一步的迭代计算,得到 h 1 h_1 h 1 :
h 1 = h 0 − Φ ( h 0 ) Φ ′ ( h 0 ) = 2 h 0 − g ⋅ h 0 2 = 2 − g h_1 = h_0 - \frac{\Phi(h_0)}{\Phi'(h_0)} = 2h_0 - g\cdot h_0^2 = 2 - g h 1 = h 0 − Φ ′ ( h 0 ) Φ ( h 0 ) = 2 h 0 − g ⋅ h 0 2 = 2 − g 我们再测下 g ⋅ h 1 g\cdot h_1 g ⋅ h 1 距离 1 有多远,
1 − g ⋅ h 1 = 1 − g ( 2 − g ) = ( 1 − g ) 2 = ( O ( X ) ) 2 = O ( X 2 ) ≡ 0 m o d X 2 1 - g\cdot h_1 = 1- g(2-g) = (1 - g)^2 = (O(X))^2 = O(X^2) \equiv 0 \mod{X^2} 1 − g ⋅ h 1 = 1 − g ( 2 − g ) = ( 1 − g ) 2 = ( O ( X ) ) 2 = O ( X 2 ) ≡ 0 mod X 2 这时我们可以认为: h 1 h_1 h 1 是精度 为 X 2 X^2 X 2 的 Φ ( Y ) \Phi(Y) Φ ( Y ) 函数的近似根。
再继续尝试迭代计算 h 2 h_2 h 2 :
h 2 = h 1 − Φ ( h 1 ) Φ ′ ( h 1 ) = 2 h 1 − g ⋅ h 1 2 = 4 − 2 g − g ( 2 − g ) 2 = 4 − 2 g − 4 g + 4 g 2 − g 3 h_2 = h_1 - \frac{\Phi(h_1)}{\Phi'(h_1)} = 2h_1 - g\cdot h_1^2 = 4 - 2g - g(2-g)^2 = 4 - 2g - 4g + 4g^2 - g^3 h 2 = h 1 − Φ ′ ( h 1 ) Φ ( h 1 ) = 2 h 1 − g ⋅ h 1 2 = 4 − 2 g − g ( 2 − g ) 2 = 4 − 2 g − 4 g + 4 g 2 − g 3 继续测试 g ⋅ h 2 g\cdot h_2 g ⋅ h 2 距离 1 有多远,假设 g = 1 + e 0 X + e 1 X 2 + e 2 X 3 + O ( X 4 ) g = 1 + e_0X + e_1X^2 + e_2X^3 + O(X^4) g = 1 + e 0 X + e 1 X 2 + e 2 X 3 + O ( X 4 ) ,那么
$$
\begin{aligned}
1 - g\cdot h_2 &= 1- g(4-6g+4g^2-g^3) \
& = 1 - 4g + 6g^2 - 4g^3 + g^4 \
\end{aligned}
$$
代入 g = 1 + e 0 X + e 1 X 2 + e 2 X 3 + O ( X 4 ) g = 1 + e_0X + e_1X^2 + e_2X^3 + O(X^4) g = 1 + e 0 X + e 1 X 2 + e 2 X 3 + O ( X 4 ) 到上式右边,略去中间的繁琐计算步骤,我们可以发现所有 X , X 2 , X 3 X, X^2, X^3 X , X 2 , X 3 项的系数都被消除为零,最终得到
1 − g ⋅ h 2 = ⋯ = O ( X 4 ) ≡ 0 m o d X 4 1 - g\cdot h_2 = \cdots = O(X^4) \equiv 0 \mod{X^4} 1 − g ⋅ h 2 = ⋯ = O ( X 4 ) ≡ 0 mod X 4 那么,h 2 h_2 h 2 是精度为 X 4 X^4 X 4 的 Φ ( X ) \Phi(X) Φ ( X ) 函数的近似根。
通过观察不难发现,每次采用牛顿迭代法都会使计算结果逐步接近 Φ ( Y ) \Phi(Y) Φ ( Y ) 的根,并且 ( 1 − g ⋅ h i ) (1-g\cdot h_i) ( 1 − g ⋅ h i ) 的尾项上只带有 X 2 i X^{2^i} X 2 i 及更高次项的项。我们可以猜测下面的结论:
g ⋅ h i ≡ 1 m o d X 2 i g\cdot h_i \equiv 1 \mod{X^{2^i}} g ⋅ h i ≡ 1 mod X 2 i 这里 h i h_i h i 通过下面的方式计算:
h i = h i − 1 − Φ ( h i − 1 ) Φ ′ ( h i − 1 ) ≡ 2 ⋅ h i − 1 − g ⋅ h i − 1 2 m o d X 2 i h_{i} = h_{i-1} - \frac{\Phi(h_{i-1})}{\Phi'(h_{i-1})} \equiv 2\cdot h_{i-1} - g\cdot h_{i-1}^2 \mod{X^{2^{i}}} h i = h i − 1 − Φ ′ ( h i − 1 ) Φ ( h i − 1 ) ≡ 2 ⋅ h i − 1 − g ⋅ h i − 1 2 mod X 2 i 我们用数学归纳法来证明上面的定理:
如果 i = 0 i = 0 i = 0 , 那么 h 0 = 1 h_0 = 1 h 0 = 1 ,显然 g ⋅ h 0 = 1 + O ( X ) ≡ 1 m o d X g\cdot h_0 = 1 + O(X) \equiv 1 \mod{X} g ⋅ h 0 = 1 + O ( X ) ≡ 1 mod X ,所以 i = 0 i=0 i = 0 时,定理成立。 假设 g ⋅ h i ≡ 1 m o d X 2 i g\cdot h_i \equiv 1 \mod{X^{2^i}} g ⋅ h i ≡ 1 mod X 2 i 成立,那么考虑 h i + 1 h_{i+1} h i + 1 ,展开 1 − g h i + 1 1-gh_{i+1} 1 − g h i + 1 ,同样证明 h i + 1 h_{i+1} h i + 1 满足定理等式: 1 − g ⋅ h i + 1 = 1 − g ⋅ ( 2 ⋅ h i − g ⋅ h i 2 ) = 1 − 2 g ⋅ h i + g 2 ⋅ h i 2 = ( 1 − g ⋅ h i ) 2 ≡ 0 m o d ( X 2 i ) 2 \begin{aligned}
1 - g\cdot h_{i+1} & = 1 - g\cdot \Big(2\cdot h_{i} - g\cdot h_{i}^2\Big) \\
& = 1 - 2g\cdot h_{i} + g^2\cdot h_{i}^2 \\
& = (1 - g\cdot h_{i})^2 \\
& \equiv 0 \mod{(X^{2^{i}})^2}
\end{aligned} 1 − g ⋅ h i + 1 = 1 − g ⋅ ( 2 ⋅ h i − g ⋅ h i 2 ) = 1 − 2 g ⋅ h i + g 2 ⋅ h i 2 = ( 1 − g ⋅ h i ) 2 ≡ 0 mod ( X 2 i ) 2 现在我们可以理解到最初为何我们要采用 r e v ( g ) \mathsf{rev}(g) rev ( g ) 函数要得到 g g g 的逆序多项式,这是由于逆序多项式被当作幂级数运算时,其常数项稳定,高次项虽然出现大量的交叉项,但是可以通过模运算抹除精度。
多项式求逆算法 ¶ 下面我们再详细列出来 h k h_k h k 的计算过程
h k + 1 ( X ) ≡ 2 ⋅ h k ( X ) − f ( X ) ⋅ h k ( X ) m o d X 2 k h k ( X ) ≡ 2 ⋅ h k − 1 ( X ) − f ( X ) ⋅ h k − 1 ( X ) m o d X 2 k − 1 ⋮ ≡ ⋮ h 2 ( X ) ≡ 2 ⋅ h 1 ( X ) − f ( X ) ⋅ h 1 ( X ) m o d X 2 h 1 ( X ) ≡ 2 ⋅ h 0 ( X ) − f ( X ) ⋅ h 0 ( X ) m o d X \begin{aligned}
h_{k+1}(X) & \equiv 2\cdot h_k(X) - f(X)\cdot h_{k}(X) \mod X^{2^k} \\
h_{k}(X) & \equiv 2\cdot h_{k-1}(X) - f(X)\cdot h_{k-1}(X) \mod X^{2^{k-1}}\\
\vdots \quad & \equiv \qquad \vdots \\
h_{2}(X) & \equiv 2\cdot h_{1}(X) - f(X)\cdot h_{1}(X) \mod X^{2}\\
h_{1}(X) & \equiv 2\cdot h_{0}(X) - f(X)\cdot h_{0}(X) \mod X\\
\end{aligned} h k + 1 ( X ) h k ( X ) ⋮ h 2 ( X ) h 1 ( X ) ≡ 2 ⋅ h k ( X ) − f ( X ) ⋅ h k ( X ) mod X 2 k ≡ 2 ⋅ h k − 1 ( X ) − f ( X ) ⋅ h k − 1 ( X ) mod X 2 k − 1 ≡ ⋮ ≡ 2 ⋅ h 1 ( X ) − f ( X ) ⋅ h 1 ( X ) mod X 2 ≡ 2 ⋅ h 0 ( X ) − f ( X ) ⋅ h 0 ( X ) mod X 如果假设 l l l 是2的整数次幂,即 l = 2 k l=2^k l = 2 k ,那么我们可以得到如下的多项式求逆算法(Python 代码),其中参数为某个已知的多项式 g ( X ) ∈ F [ X ] g(X)\in F[X] g ( X ) ∈ F [ X ] ,算法返回多项式 h ∈ F [ X ] / ⟨ X l ⟩ h\in F[X]/\langle X^l \rangle h ∈ F [ X ] / ⟨ X l ⟩ ,满足 g h ≡ 1 m o d X l gh\equiv 1 \mod{X^l} g h ≡ 1 mod X l :
def poly_inverse(g: list[F], l: int):
assert (g[0] == F.one())
r = log_2_floor(l)
h = [F(1)]
for i in range(1, k+1):
h_sq = poly_mul(h, h)
f_h_sq = poly_mul(h_sq, f)
h = poly_sub(poly_smul(h, F(2)), f_h_sq[:2**i])
return h
def poly_sub(f, g):
return [f[i] - g[i] for i in range(len(f))]
def poly_smul(f, c):
return [f[i] * c for i in range(len(f))]
def poly_mul(f, g):
''' skip the implementation '''
...
那么如果 l l l 不是2的整数次幂,应该如何处理呢?
我们有两种方法来应对。先介绍第一种方法,出自论文 [CC11]。这个方法处理非常直接,假设 k k k 是 l l l 按 2 的整数次幂对其的整数,那么 l ≤ k l\leq k l ≤ k
,我们可以有下面的结论:
X k ∣ ( 1 − g h ) ⇒ X l ∣ ( 1 − g h ) X^k\mid (1 - gh) \Rightarrow X^l\mid (1 - gh) X k ∣ ( 1 − g h ) ⇒ X l ∣ ( 1 − g h ) 这个结论非常容易证明,在这里略过。我们只要思考下直觉上它为什么成立。如果一个幂级数按照 X k X^k X k 的精度计算得到零,那么它在较低的精度进行抹除上也一定是零,这好比 1 + O ( X k ) 1 + O(X^k) 1 + O ( X k ) 一定可以表示为 1 + O ( X l ) 1 + O(X^l) 1 + O ( X l ) 。因此我们只需要计算 X k ∣ 1 − g h ∗ X^k\mid 1 - gh^* X k ∣ 1 − g h ∗ 的 h ∗ h^* h ∗ 多项式,然后通过模运算得到 h = h ∗ m o d X l h = h^*\mod{X^l} h = h ∗ mod X l ,它一定满足:
X l ∣ 1 − g h X^l\mid 1 - gh X l ∣ 1 − g h 所以我们可以通过计算 X k ∣ 1 − g h X^k\mid 1 - gh X k ∣ 1 − g h 的 h h h 多项式,然后通过模运算得到 X l ∣ 1 − g h X^l\mid 1 - gh X l ∣ 1 − g h 的 h h h 多项式。
另外一个需要处理的细节是,考虑到 g ( 0 ) g(0) g ( 0 ) 的常数项可能不是 1。这个情况非常常见,因为 g g g 的逆序多项式很可能不是一个首项为一的 Monic 多项式。虽然我们有简单的办法把一个非 Monic 多项式转换成 Monic 多项式,但是这个转换过程需要额外引入 O ( l ) O(l) O ( l ) 次有限域乘法。不过,我们可以直接去除这个限制条件,让最初始的猜测 h 0 h_0 h 0 设置为 g ( 0 ) − 1 g(0)^{-1} g ( 0 ) − 1 ,然后再继续进行后续的牛顿迭代法的计算。
第三个可以改进的点是,在每一次多项式乘法运算中,都可以事先针对精度进行多项式的截断,减少多项式的长度,从而减少计算量。比如每一次计算 g ⋅ h i − 1 2 g\cdot h_{i-1}^2 g ⋅ h i − 1 2 时,我们只需计算 ( g m o d X 2 i ) ⋅ h i − 1 2 (g\bmod{X^{2^i}})\cdot h_{i-1}^2 ( g mod X 2 i ) ⋅ h i − 1 2 ,即先对 g g g 多项式进行精度截断,再进行乘法运算。
下面是修改过后的 Python 代码:
def poly_inverse_rev1(g: list[F], l: int):
k = log_2_floor(l)
h = [g[0].inverse()]
for i in range(1, k+1):
h_sq = poly_mul(h[:2**(i-1)], h[:2**(i-1)])
g_h_sq = poly_mul(h_sq, g[:2**i])
h = poly_sub(poly_smul(h, 2), g_h_sq[:2**i])
h_sq = poly_mul(h, h)
g_h_sq = poly_mul(h_sq[:l+1], g[:l+1])
h = poly_sub(poly_smul(h[:l+1], 2), g_h_sq[:l+1])
return h
复杂度分析 ¶ 这个多项式求逆的算法时间复杂度为 3 M ( l ) + 2 l 3M(l) + 2l 3 M ( l ) + 2 l 。
首先每一轮的多项式乘法有两次,一次是 h i 2 h_i^2 h i 2 ,时间复杂度为 M ( 2 i − 1 ) M(2^{i-1}) M ( 2 i − 1 ) ,一次是 h i 2 ⋅ g h_i^2\cdot g h i 2 ⋅ g ,时间复杂度为 M ( 2 i ) M(2^i) M ( 2 i ) ,计算 2 h i − g ⋅ h i 2 2h_i - g\cdot h_i^2 2 h i − g ⋅ h i 2 的时间复杂度为 2 i 2^i 2 i 。
一次迭代的总的开销如下:
M ( 2 i ) + M ( 2 i − 1 ) + 2 i ≤ = 3 2 M ( 2 i ) + 2 i M(2^i) + M(2^{i-1}) + 2^i \leq = \frac{3}{2}M(2^{i}) + 2^i M ( 2 i ) + M ( 2 i − 1 ) + 2 i ≤= 2 3 M ( 2 i ) + 2 i 迭代 r r r 轮的总开销为:
∑ 1 ≤ i ≤ r ( 3 2 M ( 2 i ) + 2 i ) < 3 M ( 2 r ) + 2 r + 1 \sum_{1\leq i \leq r} \Big(\frac{3}{2}M(2^i) + 2^i\Big) \lt 3M(2^r) + 2^{r+1} 1 ≤ i ≤ r ∑ ( 2 3 M ( 2 i ) + 2 i ) < 3 M ( 2 r ) + 2 r + 1 多项式除法算法 ¶ 我们现在已经掌握了如何计算多项式的乘法逆元,那么接下来我们梳理下多项式除法的算法步骤。假设我们有两个多项式 f , g ∈ F [ X ] f, g\in F[X] f , g ∈ F [ X ] ,其中 f f f 的次数为 n n n ,g g g 的次数为 m m m ,并且 n ≥ m n\geq m n ≥ m ,算法的返回商多项式 q q q ,其次数为 n − m n-m n − m ,余数多项式 r r r ,其次数严格小于 m − 1 m-1 m − 1 ,它们满足下面的等式:
f ( X ) = q ( X ) ⋅ g ( X ) + r ( X ) f(X) = q(X)\cdot g(X) + r(X) f ( X ) = q ( X ) ⋅ g ( X ) + r ( X ) 算法第一步检查参数 f f f 与 g g g 的最高次项的系数不能为零,然后计算得到两者的次数之差,记为 d = deg f − deg g d=\deg{f}-\deg{g} d = deg f − deg g ,这里假设 deg f ≥ deg g \deg{f}\geq \deg{g} deg f ≥ deg g 。
第二步计算 f f f 和 g g g 的逆序多项式,记为 r e v n ( f ) \mathsf{rev}_n(f) rev n ( f ) 和 r e v m ( g ) \mathsf{rev}_m(g) rev m ( g ) ,这里 n = deg f n=\deg{f} n = deg f ,m = deg g m=\deg{g} m = deg g 。
第三步计算 r e v m ( g ) \mathsf{rev}_m(g) rev m ( g ) 在幂级数环 F [ [ X ] ] F[[X]] F [[ X ]] 上的 Inverse Element,精度为 X d + 1 X^{d+1} X d + 1 ,计算结果记为 g ~ d = r e v m ( g ) − 1 \tilde{g}_{d}=\mathsf{rev}_m(g)^{-1} g ~ d = rev m ( g ) − 1 。
第四步计算 q ∗ ≡ r e v m ( f ) ⋅ g ~ d m o d X d + 1 q^* \equiv \mathsf{rev}_m(f)\cdot \tilde{g}_d \mod X^{d+1} q ∗ ≡ rev m ( f ) ⋅ g ~ d mod X d + 1 ,记为 r e v m ( q ) \mathsf{rev}_m(q) rev m ( q ) 。
第五步计算 r e v n − m ( q ∗ ) = r e v n − m ( r e v n − m ( q ) ) = q \mathsf{rev}_{n-m}(q^*)=\mathsf{rev}_{n-m}(\mathsf{rev}_{n-m}(q))=q rev n − m ( q ∗ ) = rev n − m ( rev n − m ( q )) = q 。
第六步计算余数多项式 r = f − q ⋅ g r = f - q\cdot g r = f − q ⋅ g 。
下面给出除法的 Python 代码,然后我们再分析它的复杂度。
def poly_div_rem(f: list[F], g: list[F]):
assert(f[-1] != Fp(0))
assert(g[-1] != Fp(0))
f_deg = len(f) - 1
g_deg = len(g) - 1
if f_deg < g_deg:
return [Fp(0)], f
d = f_deg - g_deg
rev_g = g[::-1]
rev_f = f[::-1]
rev_g_inv_prec_d_plus_1 = poly_inverse_rev1(rev_g, d+1)
q = poly_mul(rev_f[:d+1], rev_g_inv_prec_d_plus_1)
q = q[:d+1]
q.reverse()
r = poly_sub(f, poly_mul(q,g))
remove_leading_zeros(r)
return q, r
复杂度分析 ¶ 算法的第三步,需要 3 M ( l ) + 2 l 3M(l) + 2l 3 M ( l ) + 2 l 次多项式乘法运算;而在第四步需要一次多项式乘法,时间复杂度为 M ( l ) M(l) M ( l ) ;第六步需要一次多项式乘法运算,时间复杂度为 M ( l ) M(l) M ( l ) ,还需要一次多项式的减法,时间复杂度为 n n n 。那么总共的时间复杂度为
5 M ( l ) + 2 l + n 5M(l) + 2l + n 5 M ( l ) + 2 l + n References ¶ OLD ¶ 我们可以快速推导一下上面这个公式,我们先用 X = 1 X X=\frac{1}{X} X = X 1 代入 f ( X ) f(X) f ( X ) 的等式,可得:
f ( 1 X ) = g ( 1 X ) ⋅ q ( 1 X ) + r ( 1 X ) f\Big(\frac{1}{X}\Big) = g\Big(\frac{1}{X}\Big)\cdot q\Big(\frac{1}{X}\Big) + r\Big(\frac{1}{X}\Big) f ( X 1 ) = g ( X 1 ) ⋅ q ( X 1 ) + r ( X 1 ) 然后两边同时乘上 X n − 1 X^{n-1} X n − 1 ,可得:
X n − 1 ⋅ f ( 1 X ) = X m − 1 ⋅ g ( 1 X ) ⋅ X n − m ⋅ q ( 1 X ) + X n − m + 1 ⋅ X m − 2 ⋅ r ( 1 X ) X^{n-1}\cdot f\Big(\frac{1}{X}\Big) = X^{m-1}\cdot g\Big(\frac{1}{X}\Big)\cdot X^{n-m}\cdot q\Big(\frac{1}{X}\Big) + X^{n-m+1}\cdot X^{m-2}\cdot r\Big(\frac{1}{X}\Big) X n − 1 ⋅ f ( X 1 ) = X m − 1 ⋅ g ( X 1 ) ⋅ X n − m ⋅ q ( X 1 ) + X n − m + 1 ⋅ X m − 2 ⋅ r ( X 1 ) 分析下等式左边 X n − 1 ⋅ f ( 1 X ) X^{n-1}\cdot f(\frac{1}{X}) X n − 1 ⋅ f ( X 1 ) ,
X n − 1 ⋅ f ( 1 X ) = X n − 1 ⋅ ( a 0 + a 1 X + ⋯ + a n − 2 X n − 2 + a n − 1 X n − 1 ) = a 0 X n − 1 + a 1 X n − 2 + ⋯ + a n − 2 X + a n − 1 = r e v n − 1 ( f ) \begin{aligned}
X^{n-1}\cdot f\Big(\frac{1}{X}\Big) & = X^{n-1}\cdot \Big(a_{0} + \frac{a_{1}}{X} + \cdots + \frac{a_{n-2}}{X^{n-2}} + \frac{a_{n-1}}{X^{n-1}}\Big) \\
& = a_{0}X^{n-1} + a_{1}X^{n-2} + \cdots + a_{n-2}X + a_{n-1} \\
& = \mathsf{rev}_{n-1}(f)
\end{aligned} X n − 1 ⋅ f ( X 1 ) = X n − 1 ⋅ ( a 0 + X a 1 + ⋯ + X n − 2 a n − 2 + X n − 1 a n − 1 ) = a 0 X n − 1 + a 1 X n − 2 + ⋯ + a n − 2 X + a n − 1 = rev n − 1 ( f ) 再分析下
X m − 1 ⋅ g ( 1 X ) = r e v m − 1 ( g ) X^{m-1}\cdot g(\frac{1}{X}) = \mathsf{rev}_{m-1}(g) X m − 1 ⋅ g ( X 1 ) = rev m − 1 ( g ) X n − m ⋅ q ( 1 X ) = r e v n − m ( q ) X^{n-m}\cdot q(\frac{1}{X}) = \mathsf{rev}_{n-m}(q) X n − m ⋅ q ( X 1 ) = rev n − m ( q ) X n − m + 1 ⋅ X m − 2 ⋅ r ( 1 X ) = X n − m + 1 ⋅ r e v m − 2 ( r ) X^{n-m+1}\cdot X^{m-2}\cdot r(\frac{1}{X}) = X^{n-m+1}\cdot \mathsf{rev}_{m-2}(r) X n − m + 1 ⋅ X m − 2 ⋅ r ( X 1 ) = X n − m + 1 ⋅ rev m − 2 ( r ) 所以,我们可以得到倒序多项式之间的关系等式:
r e v n − 1 ( f ) = r e v n − m ( q ) ⋅ r e v m − 1 ( g ) + X n − m + 1 ⋅ r e v m − 2 ( r ) \mathsf{rev}_{n-1}(f) = \mathsf{rev}_{n-m}(q)\cdot \mathsf{rev}_{m-1}(g) + {X^{n-m+1}}\cdot \mathsf{rev}_{m-2}(r) rev n − 1 ( f ) = rev n − m ( q ) ⋅ rev m − 1 ( g ) + X n − m + 1 ⋅ rev m − 2 ( r )