拉格朗日插值相关

一.插值的定义.

插值:给定若干个点 ( x i , y i ) (x_i,y_i) (xi,yi),确定一条函数曲线 f ( x ) f(x) f(x)满足对于所有 i i i,有 f ( x i ) = y i f(x_i)=y_i f(xi)=yi的过程称为插值.

多项式插值:给定 n + 1 n+1 n+1 x i x_i xi两两不同的点 ( x i , y i ) (x_i,y_i) (xi,yi),确定一个多项式 f ( x ) = ∑ i = 0 n a i x i f(x)=\sum_{i=0}^{n}a_ix^{i} f(x)=i=0naixi满足对于所有 i i i,有 f ( x i ) = y i f(x_i)=y_i f(xi)=yi的过程称为插值.

方便起见,接下来若没有说明,则下文所说的所有插值均指多项式插值.


二.朴素插值方法.

根据插值的定义,很容易列出如下方程组:
{ a 0 + a 1 x 0 + a 2 x 0 2 + ⋯ + a n x 0 n = y 0 a 0 + a 1 x 1 + a 2 x 1 2 + ⋯ + a n x 1 n = y 1 ⋮ a 0 + a 1 x n + a 2 x n 2 + ⋯ + a n x n n = y n \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=y1a0+a1xn+a2xn2++anxnn=yn

接下来只需要高斯消元,就可以在 O ( n 3 ) O(n^3) O(n3)的时间复杂度内求出这个多项式了.


三.拉格朗日插值法.

显然, O ( n 3 ) O(n^3) O(n3)的时间复杂度并不令人满意,考虑有没有其他更加优秀的算法.

拉格朗日插值法的思路是构造 n + 1 n+1 n+1个基础多项式 l i ( x ) l_i(x) li(x)满足:
l i ( x i ) = 1 j ≠ i ⇒ l i ( x j ) = 0 l_i(x_i)=1\\ j\neq i\Rightarrow l_i(x_j)=0 li(xi)=1j=ili(xj)=0

然后拉格朗日构造出了这样的基础多项式:
l i ( x ) = ∏ j ≠ i x − x j x i − x j l_i(x)=\prod_{j\neq i}\frac{x-x_j}{x_i-x_j} li(x)=j=ixixjxxj

有了这 n + 1 n+1 n+1个基础多项式,我们就可以通过它们的线性组合得到 f ( x ) f(x) f(x)
f ( x ) = ∑ i = 0 n y i l i ( x ) = ∑ i = 0 n y i ∏ j ≠ i x − x j x i − x j 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=0nyili(x)=i=0nyij=ixixjxxj

也就是说若我们直接将多项式用 n + 1 n+1 n+1个点存下来,就可以做到 O ( n 2 ) O(n^2) O(n2)计算带入某个 x x x的值.


四.求出多项式的系数表示.

乍一看,如果要计算出这个多项式的系数表示,怎么着复杂度也是 O ( n 3 ) O(n^3) O(n3)的…

其实不然,我们来转化一下:
f ( x ) = ∑ i = 0 n y i ∏ j ≠ i x − x j x i − x j = ∑ i = 0 n y i ∏ j = 0 n ( x − x j ) x − x i 1 ∏ j ≠ i ( x i − x j ) 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=0nyij=ixixjxxj=i=0nyixxij=0n(xxj)j=i(xixj)1

t i = y i ∏ j ≠ i ( x i − x j ) t_i=\frac{y_i}{\prod_{j\neq i}(x_i-x_j)} ti=j=i(xixj)yi,容易发现 t i t_i ti可以暴力计算,那么剩下的式子就是:
f ( x ) = ∑ i = 0 n t i ∏ j = 0 n ( x − x j ) x − x i f(x)=\sum_{i=0}^{n}t_i\frac{\prod_{j=0}^{n}(x-x_j)}{x-x_i} f(x)=i=0ntixxij=0n(xxj)

g ( x ) = ∏ i = 0 n ( x − x i ) g(x)=\prod_{i=0}^{n}(x-x_i) g(x)=i=0n(xxi),容易发现 g ( x ) g(x) g(x)也可以暴力算,式子变为:
f ( x ) = ∑ i = 0 n t i g ( x ) x − x i f(x)=\sum_{i=0}^{n}t_i\frac{g(x)}{x-x_i} f(x)=i=0ntixxig(x)

接下来的问题就是 O ( n ) O(n) O(n)计算 g ( x ) x − x i \frac{g(x)}{x-x_i} xxig(x),这可以用背包方案数的技巧做到.

时间复杂度 O ( n 2 ) O(n^2) O(n2).


五.利用拉格朗日插值法计算自然数幂和.

首先我们需要推一下自然数幂和的式子.记:
S k ( n ) = ∑ i = 1 n i k S_{k}(n)=\sum_{i=1}^{n}i^{k} Sk(n)=i=1nik

那么有:
S k ( n ) = S k ( n + 1 ) − ( n + 1 ) k = ∑ i = 1 n ( i + 1 ) k − ( n + 1 ) k + 1 = ∑ i = 1 n ∑ j = 0 k ( k j ) i j − ( n + 1 ) k + 1 = ∑ i = 0 k ( k i ) ∑ j = 1 n j i − ( n + 1 ) k + 1 = ∑ i = 0 k ( k i ) S i ( 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=1n(i+1)k(n+1)k+1=i=1nj=0k(jk)ij(n+1)k+1=i=0k(ik)j=1nji(n+1)k+1=i=0k(ik)Si(n)(n+1)k+1

推到这一步,我们来尝试一下推出 S k − 1 ( n ) S_{k-1}(n) Sk1(n)
S k − 1 ( n ) = 1 k ( ( n + 1 ) k − 1 − ∑ i = 0 k − 2 ( k i ) S i ( 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) Sk1(n)=k1((n+1)k1i=0k2(ik)Si(n))

也就是:
S k ( n ) = 1 k + 1 ( ( n + 1 ) k + 1 − 1 − ∑ i = 0 k − 1 ( k + 1 i ) S i ( 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+11i=0k1(ik+1)Si(n))

经过一波操作之后,我们确定了自然数幂和的式子,但是直接计算是 O ( k 2 ) O(k^2) O(k2)的,并不够优秀.

经过观察之后,我们发现这个式子必然是关于 n n n k + 1 k+1 k+1次多项式,那么接下来就是计算点和拉格朗日插值了.

计算点非常容易,对于所有 i ∈ [ 0 , k + 1 ] i\in [0,k+1] i[0,k+1],只需要计算出 i k i^{k} ik然后前缀和一下就是 S k ( i ) S_k(i) Sk(i)了,这一部分的时间复杂度为 O ( k log ⁡ k ) O(k\log k) O(klogk).

然后是拉格朗日插值,然而是 O ( k 2 ) O(k^2) O(k2)的,复杂度并没有变…

但是这不是大问题,我们观察所取的点,发现是连续的 k + 2 k+2 k+2个点,这会有什么用呢?

代入拉格朗日插值公式:
f ( n ) = ∑ i = 0 k + 1 S k ( i ) ∏ j ≠ i n − j i − j = ∑ i = 0 k + 1 S k ( i ) 1 i ! ( − 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=0k+1Sk(i)j=iijnj=i=0k+1Sk(i)i!(1)k+1i(k+1i)!1j=i(nj)

对于最后一个连乘式,我们令:
P ( i ) = ∏ j = 0 i ( n − j ) S ( i ) = ∏ j = i k + 1 ( n − j ) P(i)=\prod_{j=0}^{i}(n-j)\\ S(i)=\prod_{j=i}^{k+1}(n-j) P(i)=j=0i(nj)S(i)=j=ik+1(nj)

那么有:
f ( n ) = ∑ i = 0 k + 1 S k ( 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=0k+1Sk(i)i!(1)k+1i(k+1i)!P(i1)S(i+1)

这就可以做到 O ( k ) O(k) O(k)拉格朗日插值了.

总时间复杂度即为 O ( k log ⁡ k ) O(k\log k) O(klogk).通过一个线性筛 i k i^{k} ik的操作,可以做到 O ( k ) O(k) O(k).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值