多项式多点求值
给定 n n n个值 x i x_i xi,求 f ( x i ) f(x_i) f(xi)。
设 f 0 ( x ) = ∑ i = 0 n 2 − 1 f ( x i ) f_0(x)=\sum_{i=0}^{\frac{n}{2}-1}f(x_i) f0(x)=∑i=02n−1f(xi), P 0 ( x ) = ∏ i = 0 n 2 − 1 x − x i P_0(x)=\prod_{i=0}^{\frac{n}{2}-1}x-x_i P0(x)=∏i=02n−1x−xi。则有 f ( x ) = P 0 ( x ) z ( x ) + f 0 ( x ) f(x)=P_0(x)z(x)+f_0(x) f(x)=P0(x)z(x)+f0(x)其中 z ( x ) z(x) z(x)是某一多项式。
于是对于 i < n 2 i<\frac{n}{2} i<2n,有 f ( x i ) = ( f   m o d   P 0 ) ( x i ) f(x_i)=(f\bmod P_0)(x_i) f(xi)=(fmodP0)(xi)。后一半同样。递归计算即可,每次用分治卷积和多项式取模,复杂度为 O ( n log 2 n ) O(n\log^2n) O(nlog2n)。
多项式快速插值
给定 n n n个二元组 ( x i , y i ) (x_i,y_i) (xi,yi),求 F ( x ) F(x) F(x)使 F ( x i ) = y i F(x_i)=y_i F(xi)=yi。
由拉格朗日插值公式,
F
(
x
)
=
∑
i
∏
j
=
̸
i
(
x
−
x
j
)
∏
j
=
̸
i
(
x
i
−
x
j
)
⋅
y
i
F(x)=\sum_i\frac{\prod_{j=\not i}(x-x_j)}{\prod_{j=\not i}(x_i-x_j)}\cdot y_i
F(x)=i∑∏j≠i(xi−xj)∏j≠i(x−xj)⋅yi
设
M
(
x
)
=
∏
i
(
x
−
x
i
)
M(x)=\prod_i(x-x_i)
M(x)=∏i(x−xi),则
F
(
x
)
=
∑
i
∏
j
=
̸
i
(
x
−
x
j
)
M
(
x
i
)
x
i
−
x
i
⋅
y
i
F(x)=\sum_i\frac{\prod_{j=\not i}(x-x_j)}{\frac{M(x_i)}{x_i-x_i}}\cdot y_i
F(x)=i∑xi−xiM(xi)∏j≠i(x−xj)⋅yi
F
(
x
)
=
∑
i
∏
j
=
̸
i
(
x
−
x
j
)
M
′
(
x
i
)
⋅
y
i
F(x)=\sum_i\frac{\prod_{j=\not i}(x-x_j)}{M'(x_i)}\cdot y_i
F(x)=i∑M′(xi)∏j≠i(x−xj)⋅yi
此时可以用多项式多点求值求出所有的
M
′
(
x
i
)
M'(x_i)
M′(xi)。设
A
i
=
y
i
M
′
(
x
i
)
A_i=\frac{y_i}{M'(x_i)}
Ai=M′(xi)yi,则等式变为
F
(
x
)
=
∑
i
A
i
∏
j
=
̸
i
(
x
−
x
j
)
F(x)=\sum_iA_i\prod_{j=\not i}(x-x_j)
F(x)=i∑Aij≠i∏(x−xj)
分治即可。设两半边答案分别为
F
0
(
x
)
F_0(x)
F0(x)、
F
1
(
x
)
F_1(x)
F1(x),则
F
(
x
)
=
F
0
(
x
)
∏
i
=
m
i
d
+
1
r
(
x
−
x
i
)
+
F
1
(
x
)
∏
i
=
l
m
i
d
(
x
−
x
i
)
F(x)=F_0(x)\prod_{i=mid+1}^r(x-x_i)+F_1(x)\prod_{i=l}^{mid}(x-x_i)
F(x)=F0(x)i=mid+1∏r(x−xi)+F1(x)i=l∏mid(x−xi)
复杂度为
O
(
n
log
2
n
)
O(n\log^2n)
O(nlog2n)。
*2019.01.11 13:30:18
线性递推数列
给定长为
m
m
m的数列
a
0
,
a
1
,
⋯
 
,
a
m
−
1
a_0,a_1,\cdots,a_{m-1}
a0,a1,⋯,am−1,给定
f
(
i
)
(
i
<
m
)
f(i)(i<m)
f(i)(i<m),已知对于任意
i
≥
m
i\ge m
i≥m有
f
(
i
)
=
∑
j
=
0
m
−
1
a
j
f
(
i
−
j
)
f(i)=\sum_{j=0}^{m-1}a_jf(i-j)
f(i)=∑j=0m−1ajf(i−j),求
f
(
n
)
f(n)
f(n)。
n
=
1
0
18
n=10^{18}
n=1018,
m
=
3
×
1
0
4
m=3\times 10^4
m=3×104。
设数列 A A A满足 f n = ∑ i = 0 ∞ A i f i f_n=\sum_{i=0}^\infty A_if_i fn=∑i=0∞Aifi,则我们容易得到一个合法的数列 A A A即 A i ′ = { 0 ( i = ̸ n ) 1 ( i = n ) A'_i=\begin{cases}0(i=\not n)\\1(i=n)\end{cases} Ai′={0(i≠n)1(i=n)。若我们求得一个 A A A使其非零项的下标都在 [ 0 , m − 1 ] [0,m-1] [0,m−1],则我们可以立即求得 f ( n ) f(n) f(n)。现在考虑将 A ′ A' A′变形。
原等式变形得 f ( i ) − ∑ j = 0 i − 1 a j f ( i − j ) = 0 f(i)-\sum_{j=0}^{i-1}a_jf(i-j)=0 f(i)−j=0∑i−1ajf(i−j)=0设多项式 B i ( x ) = f ( i ) − ∑ j = 0 i − 1 a j f ( i − j ) B_i(x)=f(i)-\sum_{j=0}^{i-1}a_jf(i-j) Bi(x)=f(i)−∑j=0i−1ajf(i−j),则其恒等于 0 0 0。
考虑这样一个过程:我们已有一个合法的 A A A,其最高的非零项为 A k A_k Ak,现将 A A A赋值为 A − B k A-B_k A−Bk,则其值不变,而最高非零项的下标严格减少。因此我们对 A ′ A' A′不断做这个过程即可得到我们想要的 A A A。
事实上,“不断做这个过程”等价于将 A ′ A' A′对 B m − 1 B_{m-1} Bm−1取模。用多项式取模,我们就在 O ( m log n log m ) O(m\log n\log m) O(mlognlogm)的时间复杂度内解决了问题。*2018.12.5