历史
在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫·拉格朗日命名的一种多项式插值方法。
许多实际问题中都用函数来表示某种内在联系或规律,而不少函数都只能通过实验和观测来了解。
如对实践中的某个物理量进行观测,在若干个不同的地方得到相应的观测值,拉格朗日插值法可以找到一个多项式,其恰好在各个观测的点取到观测到的值。
这样的多项式称为拉格朗日(插值)多项式。
插值
在离散数据的基础上补插连续函数,使得这条连续曲线通过全部给定的离散数据点
插值是离散函数逼近的重要方法,利用它可通过函数在有限个点处的取值状况,估算出函数在其他点处的近似值
意义
给定 n 个点 (xi,yi) ,通过这 n 个点最多可以确定唯一的 n−1 次多项式 f(x)
形如:
⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧y1y2⋮yn=a1+a2x1+a3x12+⋯+anx1n−1=a1+a2x2+a3x22+⋯+anx2n−1⋱⋮=a1+a2xn+x3xn2+⋯+anxnn−1
计算 f(k) 的值
第一想法可以是使用高斯消元算出系数 {a} 后
直接计算 f(k)=a1+a2k+a3k2+⋯+ankn−1
但明显这样 O(n3) 的复杂度很多时候承受不了
而拉格朗日插值法的作用是快速根据点值逼近函数
拉格朗日插值法
考虑两个多项式相减
f(k)−f(x)=(a0−a0)+a1(k1−x1)+a2(k2−x2)+⋯+an(kn−xn)
其中对每一项 (ki−xi) 分解均能得到 (k−x) 这个因数
因此 f(k)≡f(x)(mod(k−x))
那么对于求解 f(k) ,我们可以设计出这样一个线性同余方程组
⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧f(k)f(k)f(k)≡y1(mod(k−x1))≡y2(mod(k−x2))⋮≡yn(mod(k−xn))
求解线性同余方程组我们应该想到 Crt
这里
M=i=1∏n(k−xi)
mi=k−xiM=j=i∏(k−xj)
f(x)=i=1∑nyimiXi
其中 Xi 是同余方程 miXi≡1(modmi) 的一个解,也就是模 (k−xi) 意义下的逆元
那么这个逆元怎么求呢
j=i∏(k−xj)≡j=i∏(k−xj−(k−xi))≡j=i∏(xi−xj)(mod(k−xi))
即 mi−1=j=i∏xi−xj1
从而得到
f(k)≡i=1∑nyimimi−1≡i=1∑nyij=i∏xi−xjk−xj(modM)
由于模意义下 f(k) 唯一,所以
f(k)=i=1∑nyij=i∏xi−xjk−xj
时间复杂度: O(n2)
重心拉格朗日插值法
对于动态点插值问题,即 m 次操作,每次删去一个插值或者加入一个插值,我们计算 f(k) 的话时间复杂度不就变成 O(n2m) 了?
这个复杂度挺高的,那么如何做呢?
我们观察一下这个式子
f(k)=i=1∑nyij=i∏xi−xjk−xj=i=1∑nyi×k−xij=1∏n(k−xj)×j=i∏(xi−xj)1
其中 j=1∏n(k−xj) 属于重复计算,令其表示为 ℓ(k)
而将 j=i∏(xi−xj)1 定义为重心权 wi
那么原式就变成了 f(k)=ℓ(k)i=1∑nk−xiyiwi
这样做的优势在于
我们每次加入点或者删去点,只需要改变 n 个 wi 的值,每个修改 O(1) 就可以解决,修改 n 个只需要 O(n)
还有 O(1) 地修改 ℓ(k)
加上计算 f(k) 整体也就是 O(n) 的时间复杂度,整体缩减了一个量级
连续自然数的拉格朗日插值法
对于 f(k)=i=1∑nyij=i∏xi−xjk−xj ,我们将 xi 换成 i
则 f(k)=i=1∑nj=i∏i−jk−j
可以注意到整个 j=i∏i−jk−j 都是可以预处理出来快速计算的
令
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧prei=j=0∏i(k−j)sufi=j=i∏n(k−j)faci=j=1∏ij
那么 f(k)=i=1∑nyifaci−1×facn−iprei−1×sufi+1
这样做可以将时间复杂度降到 O(n)
应用——自然数的幂和
求解 Sk(n)=i=1∑nik(1≤n≤109,1≤k≤106)
首先要知道这是一个 k+1 次多项式,证明如下
这里采用二项式定理证明
在 k=d 时提出一项做差
==(i+1)d−idj=0∑(jd)ij−idj=0∑d−1(jd)ij
对 (i+1)d−id 求和 =i=1∑n−1j=0∑d−1(jd)ij=j=0∑d−1(jd)i=1∑n−1ij=j=0∑d−1(jd)Sj(n−1)
同时等式左侧经过两两相消也可以得到 nd−1
所以 nd−1=j=0∑d−1(jd)Sj(n−1) ,提出右侧 j=d−1 时对 Sd−1(n−1)
(d−1d)Sd(n−1)Sd−1(n−1)=nd−j=0∑d−2((jd)Sj(n−1))−1=d1(nd−j=0∑d−2((jd)Sj(n−1))−1)
此时是 Sd−1(n−1) ,我们将其提到 Sd(n)
Sd(n)==d+11((n+1)d+1−j=0∑d−1((jd+1)Sj(n))−1)d+11(j=0∑d+1(jd+1)nj−j=0∑d−1((jd+1)Sj(n))−1)
其中 j=0∑d+1(jd+1)ni 是一个 d+1 次多项式且就这里次数最高,所以 Sd(n) 是一个 d+1 次多项式
得证
那么在求解 Sk(n)=i=1∑nik 时
我们任取 k+2 个点以确定这个 k+1 次多项式
即 {[i:1→k+2]:(i,j=1∑ijk)}
由于 xi 连续所以我们直接使用连续自然数的拉格朗日插值法求解即可