引入

插值是一种通过已知的、离散的数据点推算一定范围内的新数据点的方法。插值法常用于函数拟合中。

例如对数据点:

其中 未知,插值法可以通过按一定形式拟合 的方式估算未知的数据点。

例如,我们可以用分段线性函数拟合

这种插值方式叫做 线性插值

我们也可以用多项式拟合

这种插值方式叫做 多项式插值

多项式插值的一般形式如下:

多项式插值

对已知的 的点 ,求形如 且满足

的多项式

下面介绍多项式插值中的两种方式:Lagrange 插值法与 Newton 插值法。不难证明这两种方法得到的结果是相等的。

Lagrange 插值法

由于要求构造一个函数 过点 . 首先设第 个点在 轴上的投影为 .

考虑构造 个函数 ,使得对于第 个函数 ,其图像过 ,则可知题目所求的函数 .

那么可以设 ,将点 代入可以知道 ,所以

那么我们就可以得出 Lagrange 插值的形式为:

朴素实现的时间复杂度为 ,可以优化到 ,参见 多项式快速插值

给出 个点对 ,且 (定义 ),求 .

横坐标是连续整数的 Lagrange 插值

如果已知点的横坐标是连续整数,我们可以做到 插值。

设要求的多项式为 ,我们已知 ),考虑代入上面的插值公式:

后面的累乘可以分子分母分别考虑,不难得到分子为:

分母的 累乘可以拆成两段阶乘来算:

于是横坐标为 的插值公式:

预处理 前后缀积、阶乘阶乘逆,然后代入这个式子,复杂度为 .

给出 ,求 取模的值。

Newton 插值法

Newton 插值法是基于高阶差分来插值的方法,优点是支持 插入新数据点。

为了实现 插入新数据点,我们令:

其中 称为 Newton 基(Newton basis)。

若解出 ,则可得到 的插值多项式。我们按如下方式定义 前向差商(forward divided differences):

则:

此即 Newton 插值的形式。朴素实现的时间复杂度为 .

若样本点是等距的(即 ),我们可以推出

其中 前向差分(forward differences),定义如下:

,则 Newton 插值的公式可化为

横坐标是连续整数的 Newton 插值

例如:求多项式 的系数,已知 的值分别为

第一行为 的连续的前 项;之后的每一行为之前一行中对应的相邻两项之差。观察到,如果这样操作的次数足够多(前提是 为多项式),最终总会返回一个定值。

计算出第 阶差分的首项为 ,第 阶差分的首项对 的贡献为 次。

时间复杂度为 .

C++ 中的实现

自 C++ 20 起,标准库添加了 std::midpointstd::lerp 函数,分别用于求中点和线性插值。

习题

参考资料

  1. Interpolation - Wikipedia
  2. Newton polynomial - Wikipedia