目的是多项式乘法,用一个n+m-2次多项式表示n-1次多项式乘上一个m-1次多项式。(以下把默认n=m,因为我懒,逃)
暴力的暴力
朴素的式子是
C
(
x
)
=
A
(
x
)
×
B
(
x
)
=
∑
k
=
0
2
n
−
2
(
∑
k
=
i
+
j
a
i
b
j
)
x
k
C(x)=A(x)×B(x)=\sum^{2n-2}_{k=0}(\sum_{k=i+j}a_ib_j)x^k
C(x)=A(x)×B(x)=∑k=02n−2(∑k=i+jaibj)xk
显然直接相乘的复杂度是
Θ
(
n
2
)
\Theta(n^2)
Θ(n2)。
引理1
对于一个n-1次多项式在n个不同点的取值唯一确定了该多项式。
粗略证明(反证法)
假设命题不成立,则存在两个多项式
A
(
x
)
A(x)
A(x)和
B
(
x
)
B(x)
B(x),使得
i
∈
[
0
,
n
−
1
]
,
都
有
A
(
x
i
)
=
B
(
x
i
)
i\in[0,n-1],都有A(x_i)=B(x_i)
i∈[0,n−1],都有A(xi)=B(xi)。
令
C
(
x
)
=
A
(
x
)
−
B
(
x
)
C(x)=A(x)-B(x)
C(x)=A(x)−B(x),则有
i
∈
[
0
,
n
−
1
]
,
C
(
x
i
)
=
0
i\in[0,n-1],C(x_i)=0
i∈[0,n−1],C(xi)=0。
即
C
(
x
)
C(x)
C(x)有n个根,这与代数基本定理(一个n-1次多项式在复平面上有且仅有n-1个根)相矛盾。所以C(x)并不是n-1次的多项式,原命题成立。证毕。
伟大的尝试
利用点坐标来确定多项式,求其系数表示我们可以用插值,但朴素插值的复杂度是
Θ
(
n
2
)
\Theta(n^2)
Θ(n2)。
但没关系,我们先用点坐标“表示出这个多项式”。
如果使用两个多项式在2n-1个点处取得的点值表示,那么有
y
3
i
=
(
∑
i
=
0
2
n
−
1
a
j
x
i
j
)
∗
(
∑
i
=
0
2
n
−
1
b
j
x
i
j
)
=
y
1
i
∗
y
2
i
y3_i=(\sum^{2n-1}_{i=0}a_jx^j_i)*(\sum^{2n-1}_{i=0}b_jx^j_i)=y1_i*y2_i
y3i=(∑i=02n−1ajxij)∗(∑i=02n−1bjxij)=y1i∗y2i
时间复杂度为
Θ
(
n
)
\Theta(n)
Θ(n)
快速傅里叶变换
说白了就是一个快速把多项式变成点值的算法。
时间复杂度为
Θ
(
n
l
o
g
2
n
)
\Theta(nlog_2n)
Θ(nlog2n)
知识储备:负数&单位根。
利用复数根的无比优越性,我们用
ω
n
0
\omega^0_n
ωn0表示n次单位根,分别求出
ω
n
0
,
ω
n
1
.
.
.
.
.
.
ω
n
n
−
1
\omega^0_n,\omega^1_n......\omega^{n-1}_n
ωn0,ωn1......ωnn−1的点值。
本身如果朴素暴力求点值还是
Θ
(
n
2
)
\Theta(n^2)
Θ(n2)的算法,但由于单位根的优越性:
ω
2
n
2
k
=
ω
n
k
和
ω
n
k
+
n
2
=
−
ω
n
k
\omega^{2k}_{2n}=\omega^k_n和\omega^{k+\frac{n}{2}}_n=-\omega^k_n
ω2n2k=ωnk和ωnk+2n=−ωnk
我们可以每次对求解点值的过程进行奇偶划分:
A
(
x
)
=
(
x
0
+
a
2
x
2
+
a
4
x
4
+
.
.
.
.
.
+
a
n
−
2
x
n
−
2
+
(
a
1
x
+
a
3
x
3
+
a
5
x
5
+
.
.
.
.
.
.
+
a
n
−
1
x
n
−
1
)
A(x)=(x_0+a_2x^2+a_4x^4+.....+a_{n-2}x^{n-2}+(a_1x+a_3x^3+a_5x^5+......+a_{n-1}x^{n-1})
A(x)=(x0+a2x2+a4x4+.....+an−2xn−2+(a1x+a3x3+a5x5+......+an−1xn−1)
并令
A
1
(
x
)
=
a
0
+
a
2
x
1
+
a
4
x
2
+
.
.
.
.
.
.
+
a
n
−
2
x
n
2
−
1
\qquad\qquad\qquad\qquad A_1(x)=a_0+a_2x^1+a_4x^2+......+a_{n-2}x^{\frac{n}{2}-1}
A1(x)=a0+a2x1+a4x2+......+an−2x2n−1
A
2
(
x
)
=
a
0
+
a
2
x
1
+
a
4
x
2
+
.
.
.
.
.
.
+
a
n
−
1
x
n
2
−
1
\qquad\qquad\qquad\qquad A_2(x)=a_0+a_2x^1+a_4x^2+......+a_{n-1}x^{\frac{n}{2}-1}
A2(x)=a0+a2x1+a4x2+......+an−1x2n−1
则有 A ( x ) = A 1 ( x 2 ) + x A ( x 2 ) A(x)=A_1(x^2)+xA(x^2) A(x)=A1(x2)+xA(x2)
假设
k
<
n
2
k<\frac{n}{2}
k<2n现在要求
A
(
ω
n
k
)
A(\omega^k_n)
A(ωnk)
A
(
ω
n
k
)
=
A
1
(
ω
n
2
k
)
+
ω
n
k
A
2
(
ω
n
2
k
)
\qquad\qquad\qquad\qquad A(\omega^k_n)=A_1(\omega^{2k}_n)+\omega^k_nA_2(\omega^{2k}_n)
A(ωnk)=A1(ωn2k)+ωnkA2(ωn2k)
=
A
1
(
ω
n
2
k
)
+
ω
n
k
A
2
(
ω
n
2
k
)
\qquad\qquad\qquad\qquad \qquad\quad =A_1(\omega^k_{\frac{n}{2}})+\omega^k_nA_2(\omega^k_{\frac{n}{2}})
=A1(ω2nk)+ωnkA2(ω2nk)
对于另一组
A
(
ω
n
k
+
n
2
)
A(\omega^{k+\frac{n}{2}}_n)
A(ωnk+2n)利用性质二转化到
A
(
ω
n
k
+
n
2
)
=
A
1
(
ω
n
2
k
+
n
)
+
ω
n
k
+
n
2
A
2
(
ω
n
2
k
+
n
)
\qquad\qquad\qquad\qquad A(\omega^{k+\frac{n}{2}}_n)=A_1(\omega^{2k+n}_n)+\omega^{k+\frac{n}{2}}_nA_2(\omega^{2k+n}_n)
A(ωnk+2n)=A1(ωn2k+n)+ωnk+2nA2(ωn2k+n)
 
=
A
1
(
ω
n
2
k
)
−
ω
n
k
A
2
(
ω
n
2
k
)
\qquad\qquad\qquad\qquad \qquad\qquad\,=A_1(\omega^{2k}_n)-\omega^k_nA_2(\omega^{2k}_n)
=A1(ωn2k)−ωnkA2(ωn2k)
 
=
A
1
(
ω
n
2
k
)
−
ω
n
k
A
2
(
ω
n
2
k
)
\qquad\qquad\qquad\qquad \qquad\qquad\,=A_1(\omega^k_{\frac{n}{2}})-\omega^k_nA_2(\omega^k_{\frac{n}{2}})
=A1(ω2nk)−ωnkA2(ω2nk)
此时只要取遍
k
∈
[
0
,
n
2
−
1
]
k\in[0,\frac{n}{2}-1]
k∈[0,2n−1],k和
k
+
n
2
k + \frac{n}{2}
k+2n取遍了
[
0
,
n
−
1
]
[0,n - 1]
[0,n−1]
本质是分治,所以时间复杂度为
T
(
n
)
=
2
T
(
n
2
)
+
Θ
(
n
)
=
Θ
(
n
l
o
g
2
n
)
\qquad\qquad\qquad\qquad T(n)=2T(\frac{n}{2})+\Theta(n)=\Theta(nlog_2n)
T(n)=2T(2n)+Θ(n)=Θ(nlog2n)
啊,优秀的cooley-Tukey算法。
傅里叶逆变换
FFT的重要组成部分。如果我们的朴素的利用点值计算系数,那么复杂度显然是
Θ
(
n
2
)
\Theta(n^2)
Θ(n2)的。
所以我们需要逆变换来配合以降低整个算法的时间复杂度。
本质上还是一个傅里叶变换,继续运用的单位根的无比优越性。
把之前得到的2n-2个y值作为一个临时性的2n-2次多项式的系数,带入单位根的倒数(共轭复数),求得新的点值ci再除以n即为。即为多项式乘法之后的系数。
总复杂度为
Θ
(
n
l
o
g
2
n
)
\Theta(nlog_2n)
Θ(nlog2n)
详细的推导过程可见FFT 学习笔记 | menci’s Blog
良心博文值得一看。