拉格朗日插值

拉格朗日插值

朴素的拉格朗日插值

  插值就是有 n n n 个已知的平面直角坐标系中的点,然后求出一个 n − 1 n-1 n1 次多项式,这个多项式穿过这些点。

{ x } : x 0 , x 1 , x 2 , ⋯   , x n { y } : y 0 , y 1 , y 2 , ⋯   , y n \{ x \} : x_0, x_1, x_2, \cdots, x_n \\ \{ y \} : y_0, y_1, y_2, \cdots, y_n {x}:x0,x1,x2,,xn{y}:y0,y1,y2,,yn

  然后我们要找到一个 f ( x ) f(x) f(x) 穿过这些点。拉格朗日插值给出了一种显然的 O ( n 2 ) O(n^2) O(n2) 的构造方法,也就是:

f ( x ) = ∑ k = 0 n ∏ i = 0 , i ≠ k n ( x − x i ) ∏ i = 0 , i ≠ k n ( x k − x i ) y k f(x) = \sum_{k=0}^n \frac{\prod\limits_{i=0, i \neq k}^n (x-x_i)}{\prod\limits_{i=0, i \neq k}^n (x_k - x_i)}y_k f(x)=k=0ni=0,i=kn(xkxi)i=0,i=kn(xxi)yk

  正确性非常显然qwq。

重心拉格朗日插值

  我们观察一下上面的式子,我们发现我们每次求解一个 f ( x ) f(x) f(x) 的时间复杂度就是 O ( n 2 ) O(n^2) O(n2),但是我们如果要求出这个 n n n 次多项式的各个项的系数的话那么时间复杂度就上升到了 O ( n 3 ) O(n^3) O(n3)。这个时间复杂度就和普通的高斯消元没有区别了。所以,我们要考虑如何优化朴素的拉格朗日插值,这时候就要引出重心拉格朗日插值了。

第一个小小的优化

  首先我们来看看这个朴素法的式子:

f ( k ) = ∑ i = 0 n y i ∏ j = 0 , j ≠ i n k − x j x i − x j f(k) = \sum_{i=0}^n y_i \prod_{j = 0,j \neq i}^n \frac{k - x_j}{x_i - x_j} f(k)=i=0nyij=0,j=inxixjkxj

  我们 很难 发现在 x x x 的取值是连续(也就是说我们知道 ( 1 , f ( 1 ) ) , ( 2 , f ( 2 ) ) , ( 3 , f ( 3 ) ) , ⋯ (1, f(1)), (2, f(2)), (3, f(3)), \cdots (1,f(1)),(2,f(2)),(3,f(3)), 的时候)的时候有一种优化时间复杂度的方法。在这种情况下显然有 x i = 1 , x j = j x_i = 1, x_j = j xi=1,xj=j。所以这个式子就可以变成这样:

f ( k ) = ∑ i = 0 n y i ∏ j = 0 , j ≠ i n k − j i − j f(k) = \sum_{i = 0}^ny_i \prod_{j = 0, j \neq i}^n \frac{k - j}{i - j} f(k)=i=0nyij=0,j=inijkj

  这样之后我们就可以用一些简单的预处理来做到 O ( n ) O(n) O(n) 预处理 O ( 1 ) O(1) O(1) 查询 ∏ j = 0 , j ≠ i n k − j i − j \prod\limits_{j=0, j\neq i}^n \frac{k-j}{i-j} j=0,j=inijkj 这一坨东西。具体可以这样:我破门预处理

p r e i = ∏ j = 0 i ( k − j ) s u f i = ∏ j = i n ( k − j ) f a c i = ∏ p = 1 i p = i ! \begin{aligned} & pre_i = \prod_{j=0}^i (k-j) \\ & suf_i = \prod_{j = i}^n (k-j) \\ & fac_i = \prod_{p=1}^i p = i! \end{aligned} prei=j=0i(kj)sufi=j=in(kj)faci=p=1ip=i!

  之后我们就有:

∏ j = 0 , j ≠ i n k − j i − j = p r e i − 1 × s u f i + 1 f a c i × f a c n − i × ( − 1 ) n − i \prod_{j = 0, j \neq i}^n \frac{k-j}{i-j} = \frac{pre_{i-1} \times suf_{i+1}}{fac_{i} \times fac_{n-i} \times (-1)^{n-i}} j=0,j=inijkj=faci×facni×(1)niprei1×sufi+1

  那么整个式子就变成了:

f ( k ) = ∑ i = 0 n y i p r e i − 1 × s u f i + 1 f a c i × f a c n − i × ( − 1 ) n − i f(k) = \sum_{i=0}^n y_i \frac{pre_{i-1} \times suf_{i+1}}{fac_{i} \times fac_{n-i} \times (-1)^{n-i}} f(k)=i=0nyifaci×facni×(1)niprei1×sufi+1

  这样之后我们就可以在 O ( n ) O(n) O(n) 的时间内算出某一个具体的 f ( a ) f(a) f(a)。但是要知道这个表达式各项的系数还是需要 O ( n 3 ) O(n^3) O(n3) 的时间才能算出来。

正题:重心拉格朗日插值

  重心拉格朗日插值能做到比上面的 O ( n 3 ) O(n^3) O(n3) 快很多的求出一个式子的表达式各项系数,而且还能做到让你新添加一个点然后快速算出新的多项式的表达式,这比前面的东西都要优秀。现在我们来看看这是怎么做到的。

  首先我们发现了一件事,就是说在 ∏ j = 0 , j ≠ i n k − x j x i − x j \prod\limits_{j=0, j \neq i}^n\frac{k - x_j}{x_i - x_j} j=0,j=inxixjkxj 这一坨式子里面每个分子都是 k − x j k - x_j kxj 然后呢我们就这样:

  令:

g ( k ) = ∏ i = 0 n ( k − x i ) g(k) = \prod_{i=0}^n (k - x_i) g(k)=i=0n(kxi)

  然后:

f ( k ) = g ( k ) ∑ i = 0 n y i k − x i ∏ j = 0 , j ≠ i n 1 x i − x j f(k) = g(k) \sum_{i = 0}^n \frac{y_i}{k - x_i} \prod_{j=0, j\neq i}^n \frac{1}{x_i - x_j} f(k)=g(k)i=0nkxiyij=0,j=inxixj1

  再令:

t i = ∏ j = 0 , j ≠ i n 1 x i − x j t_i = \prod_{j = 0, j \neq i}^n \frac{1}{x_i - x_j} ti=j=0,j=inxixj1

  那么:

f ( k ) = g ( k ) ∑ i = 0 n y i t i k − x i f(k) = g(k)\sum_{i=0}^n \frac{y_it_i}{k-x_i} f(k)=g(k)i=0nkxiyiti

  可以很明显的看出,如果我们多家进去一个点 ( x n + 1 , y n + 1 ) (x_{n+1}, y_{n+1}) (xn+1,yn+1),我们只需要将每一个 t i t_i ti 都除以一个 x i − x n + 1 x_i - x_{n+1} xixn+1,这样就可以 O ( n ) O(n) O(n) 的得到新的 ∑ i = 0 n y i t i k − x i \sum\limits_{i=0}^n\frac{y_it_i}{k - x_i} i=0nkxiyiti。然后再与新的 g ( k ) g(k) g(k) 乘起来就得到了新的多项式。总的时间复杂度就是 O ( n ) O(n) O(n),非常的快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值