一.插值的定义.
插值:给定若干个点(xi,yi)(x_i,y_i)(xi,yi),确定一条函数曲线f(x)f(x)f(x)满足对于所有iii,有f(xi)=yif(x_i)=y_if(xi)=yi的过程称为插值.
多项式插值:给定n+1n+1n+1个xix_ixi两两不同的点(xi,yi)(x_i,y_i)(xi,yi),确定一个多项式f(x)=∑i=0naixif(x)=\sum_{i=0}^{n}a_ix^{i}f(x)=∑i=0naixi满足对于所有iii,有f(xi)=yif(x_i)=y_if(xi)=yi的过程称为插值.
方便起见,接下来若没有说明,则下文所说的所有插值均指多项式插值.
二.朴素插值方法.
根据插值的定义,很容易列出如下方程组:
{a0+a1x0+a2x02+⋯+anx0n=y0a0+a1x1+a2x12+⋯+anx1n=y1⋮a0+a1xn+a2xn2+⋯+anxnn=yn
\left\{\begin{matrix}
a_0+a_1x_0+a_2x_0^2+\cdots+a_nx_0^n=y_0\\
a_0+a_1x_1+a_2x_1^2+\cdots+a_nx_1^n=y_1\\
\vdots\\
a_0+a_1x_n+a_2x_n^2+\cdots+a_nx_n^n=y_n
\end{matrix}\right.
⎩⎪⎪⎪⎨⎪⎪⎪⎧a0+a1x0+a2x02+⋯+anx0n=y0a0+a1x1+a2x12+⋯+anx1n=y1⋮a0+a1xn+a2xn2+⋯+anxnn=yn
接下来只需要高斯消元,就可以在O(n3)O(n^3)O(n3)的时间复杂度内求出这个多项式了.
三.拉格朗日插值法.
显然,O(n3)O(n^3)O(n3)的时间复杂度并不令人满意,考虑有没有其他更加优秀的算法.
拉格朗日插值法的思路是构造n+1n+1n+1个基础多项式li(x)l_i(x)li(x)满足:
li(xi)=1j≠i⇒li(xj)=0
l_i(x_i)=1\\
j\neq i\Rightarrow l_i(x_j)=0
li(xi)=1j=i⇒li(xj)=0
然后拉格朗日构造出了这样的基础多项式:
li(x)=∏j≠ix−xjxi−xj
l_i(x)=\prod_{j\neq i}\frac{x-x_j}{x_i-x_j}
li(x)=j=i∏xi−xjx−xj
有了这n+1n+1n+1个基础多项式,我们就可以通过它们的线性组合得到f(x)f(x)f(x):
f(x)=∑i=0nyili(x)=∑i=0nyi∏j≠ix−xjxi−xj
f(x)=\sum_{i=0}^{n}y_il_i(x)=\sum_{i=0}^{n}y_i\prod_{j\neq i}\frac{x-x_j}{x_i-x_j}
f(x)=i=0∑nyili(x)=i=0∑nyij=i∏xi−xjx−xj
也就是说若我们直接将多项式用n+1n+1n+1个点存下来,就可以做到O(n2)O(n^2)O(n2)计算带入某个xxx的值.
四.求出多项式的系数表示.
乍一看,如果要计算出这个多项式的系数表示,怎么着复杂度也是O(n3)O(n^3)O(n3)的…
其实不然,我们来转化一下:
f(x)=∑i=0nyi∏j≠ix−xjxi−xj=∑i=0nyi∏j=0n(x−xj)x−xi1∏j≠i(xi−xj)
f(x)=\sum_{i=0}^{n}y_i\prod_{j\neq i}\frac{x-x_j}{x_i-x_j}\\
=\sum_{i=0}^{n}y_i\frac{\prod_{j=0}^{n}(x-x_j)}{x-x_i}\frac{1}{\prod_{j\neq i}(x_i-x_j)}
f(x)=i=0∑nyij=i∏xi−xjx−xj=i=0∑nyix−xi∏j=0n(x−xj)∏j=i(xi−xj)1
令ti=yi∏j≠i(xi−xj)t_i=\frac{y_i}{\prod_{j\neq i}(x_i-x_j)}ti=∏j=i(xi−xj)yi,容易发现tit_iti可以暴力计算,那么剩下的式子就是:
f(x)=∑i=0nti∏j=0n(x−xj)x−xi
f(x)=\sum_{i=0}^{n}t_i\frac{\prod_{j=0}^{n}(x-x_j)}{x-x_i}
f(x)=i=0∑ntix−xi∏j=0n(x−xj)
令g(x)=∏i=0n(x−xi)g(x)=\prod_{i=0}^{n}(x-x_i)g(x)=∏i=0n(x−xi),容易发现g(x)g(x)g(x)也可以暴力算,式子变为:
f(x)=∑i=0ntig(x)x−xi
f(x)=\sum_{i=0}^{n}t_i\frac{g(x)}{x-x_i}
f(x)=i=0∑ntix−xig(x)
接下来的问题就是O(n)O(n)O(n)计算g(x)x−xi\frac{g(x)}{x-x_i}x−xig(x),这可以用背包方案数的技巧做到.
时间复杂度O(n2)O(n^2)O(n2).
五.利用拉格朗日插值法计算自然数幂和.
首先我们需要推一下自然数幂和的式子.记:
Sk(n)=∑i=1nik
S_{k}(n)=\sum_{i=1}^{n}i^{k}
Sk(n)=i=1∑nik
那么有:
Sk(n)=Sk(n+1)−(n+1)k=∑i=1n(i+1)k−(n+1)k+1=∑i=1n∑j=0k(kj)ij−(n+1)k+1=∑i=0k(ki)∑j=1nji−(n+1)k+1=∑i=0k(ki)Si(n)−(n+1)k+1
S_k(n)=S_k(n+1)-(n+1)^{k}\\
=\sum_{i=1}^{n}(i+1)^{k}-(n+1)^{k}+1\\
=\sum_{i=1}^{n}\sum_{j=0}^{k}\binom{k}{j}i^{j}-(n+1)^{k}+1\\
=\sum_{i=0}^{k}\binom{k}{i}\sum_{j=1}^{n}j^{i}-(n+1)^{k}+1\\
=\sum_{i=0}^{k}\binom{k}{i}S_{i}(n)-(n+1)^{k}+1
Sk(n)=Sk(n+1)−(n+1)k=i=1∑n(i+1)k−(n+1)k+1=i=1∑nj=0∑k(jk)ij−(n+1)k+1=i=0∑k(ik)j=1∑nji−(n+1)k+1=i=0∑k(ik)Si(n)−(n+1)k+1
推到这一步,我们来尝试一下推出Sk−1(n)S_{k-1}(n)Sk−1(n):
Sk−1(n)=1k((n+1)k−1−∑i=0k−2(ki)Si(n))
S_{k-1}(n)=\frac{1}{k}\left((n+1)^{k}-1-\sum_{i=0}^{k-2}\binom{k}{i}S_i(n)\right)
Sk−1(n)=k1((n+1)k−1−i=0∑k−2(ik)Si(n))
也就是:
Sk(n)=1k+1((n+1)k+1−1−∑i=0k−1(k+1i)Si(n))
S_{k}(n)=\frac{1}{k+1}\left((n+1)^{k+1}-1-\sum_{i=0}^{k-1}\binom{k+1}{i}S_{i}(n)\right)
Sk(n)=k+11((n+1)k+1−1−i=0∑k−1(ik+1)Si(n))
经过一波操作之后,我们确定了自然数幂和的式子,但是直接计算是O(k2)O(k^2)O(k2)的,并不够优秀.
经过观察之后,我们发现这个式子必然是关于nnn的k+1k+1k+1次多项式,那么接下来就是计算点和拉格朗日插值了.
计算点非常容易,对于所有i∈[0,k+1]i\in [0,k+1]i∈[0,k+1],只需要计算出iki^{k}ik然后前缀和一下就是Sk(i)S_k(i)Sk(i)了,这一部分的时间复杂度为O(klogk)O(k\log k)O(klogk).
然后是拉格朗日插值,然而是O(k2)O(k^2)O(k2)的,复杂度并没有变…
但是这不是大问题,我们观察所取的点,发现是连续的k+2k+2k+2个点,这会有什么用呢?
代入拉格朗日插值公式:
f(n)=∑i=0k+1Sk(i)∏j≠in−ji−j=∑i=0k+1Sk(i)1i!(−1)k+1−i(k+1−i)!∏j≠i(n−j)
f(n)=\sum_{i=0}^{k+1}S_k(i)\prod_{j\neq i}\frac{n-j}{i-j}\\
=\sum_{i=0}^{k+1}S_k(i)\frac{1}{i!(-1)^{k+1-i}(k+1-i)!}\prod_{j\neq i}(n-j)
f(n)=i=0∑k+1Sk(i)j=i∏i−jn−j=i=0∑k+1Sk(i)i!(−1)k+1−i(k+1−i)!1j=i∏(n−j)
对于最后一个连乘式,我们令:
P(i)=∏j=0i(n−j)S(i)=∏j=ik+1(n−j)
P(i)=\prod_{j=0}^{i}(n-j)\\
S(i)=\prod_{j=i}^{k+1}(n-j)
P(i)=j=0∏i(n−j)S(i)=j=i∏k+1(n−j)
那么有:
f(n)=∑i=0k+1Sk(i)P(i−1)∗S(i+1)i!(−1)k+1−i(k+1−i)!
f(n)=\sum_{i=0}^{k+1}S_k(i)\frac{P(i-1)*S(i+1)}{i!(-1)^{k+1-i}(k+1-i)!}
f(n)=i=0∑k+1Sk(i)i!(−1)k+1−i(k+1−i)!P(i−1)∗S(i+1)
这就可以做到O(k)O(k)O(k)拉格朗日插值了.
总时间复杂度即为O(klogk)O(k\log k)O(klogk).通过一个线性筛iki^{k}ik的操作,可以做到O(k)O(k)O(k).
本文详细介绍了多项式插值的概念,包括朴素插值方法和拉格朗日插值法,以及如何利用拉格朗日插值法高效计算自然数幂和。通过对自然数幂和公式的推导,结合拉格朗日插值法,实现了多项式插值的高效计算。
10万+

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



