拉格朗日插值法

文章可能不是很完善,只是一次模拟赛中的题考到了,于是有了这篇博客。

插值:已知一些离散的数据(点对),求一个函数经过所有离散的数据点。

正文

本来以为会很难,但是确实思想非常简单。

现已知 \(n\) 个点对,\((x_1,y_1),(x_2,y_2)\dots (x_n,y_n)\) ,欲构造出函数 \(F(x)\) 通过这 \(n\) 个点。

放出柿子:\(\displaystyle F(x)=\sum_{i=1}^{n}{y_i\times \frac{\prod_{j\neq i}(x-x_j)}{\prod_{j\neq i}{(x_i-x_j)}}}\)

可以看出,满足经过所有点对。

核心思想:对于每一个点构造一个函数 \(\displaystyle f_i=\frac{\prod_{j\neq i}(x-x_j)}{\prod_{j\neq i}{(x_i-x_j)}}\),使 \(f_i(x_i)=1,f_i(x_j)=0\) ,最后令 \(F(x)=\sum_{i=1}^{n}{y_i*f_i(x)}\) 即可。

【模板】拉格朗日插值 - 洛谷

核心代码

LL ans = 0;
for (int i = 1; i <= n; i++)
{
    int fi = 1;
    for (int j = 1; j <= n; j++)
        if (j != i) fi = mul(mul(fi, k - t[j].x), inv(t[i].x - t[j].x));
    ans = (ans + mul(fi, t[i].y)) % mod;
}

重心拉格朗日插值法

观察普通拉格朗日插值的柿子,发现 \(f_i(x)\) 有很多相似的地方。记 \(\displaystyle t(x)=\prod_{j=1}^{n}{(x-x_j)}, w_i=\frac{1}{\prod_{j\neq i}{(x_i-x_j)}}\)

那么 \(\displaystyle F(x)=\sum_{i=1}^{n}{y_i\frac{t(x)*w_i}{x-x_i}}\)

对于这种方法,每次加一个值过后,就可以做到 \(O(n)\) 修改了。

线性拉格朗日插值法

\(n\) 个点是连续的时候,我们可以做到询问线性。

\(n\) 个点分别为 \((1,f(1)),(2,f(2))\dots (n,f(n))\)

代入式子就是 \(\displaystyle \sum_{i=1}^{n}{\frac{\prod_{j\neq i}{(x-j)}}{\prod_{j\neq i} (i-j)}}\)

等价于 \(\displaystyle \sum_{i=1}^{n}{f(i)\times (-1)^{n-i}*\frac{\prod_{j\neq i}{(x-j)}}{(i-1)!(n-i)!}}\)

预处理出 \((x-j)\) 的前后缀积即可。

具体来讲:预处理 \((x-j)\) 的前后缀积 \(pre[i], suf[i]\),每次分母的计算就可以直接 \(pre[i-1]*suf[n-i]\)

posted @ 2022-09-05 16:41  mklzc  阅读(213)  评论(0编辑  收藏  举报