题解:P4781 【模板】拉格朗日插值

学生听了 \(\infty\) 道拉格朗日插值的题,于是来学学。


设第 \(i\) 个点 \(P_i(x_i,y_i)\)\(x\) 轴上的投影为 \(P^{\prime}_i(x_i,0)\)

那么考虑构造一个函数 \(f_x(i)\) 经过点 \(\begin{cases} P_i(x_i,y_i) \\ P^{\prime}_{j}(x_j,0) & j\neq i \\\end{cases}\)

那么我们最终求的函数 \(f(x)\) 则为 \(\sum^n_{i=1} f_i(x)\)

Proof: 当 \(x = x_1\) 的时候 \(f(x_1) = y_1 + \sum^n_{i = 2} 0 = y_1\),当 \(x = x_2\) 的时候 \(f(x_2) = 0 + y_2 + \sum^n_{i=3}0 = y_2\)。依此类推。

那么此时我们的问题就变成了如何构造一个 \(f_i(x)\)

根据初中的因式定理即当 \(f_i(x_j) = 0\) 时,\(f_i(x)\) 必定包含 \((x - x_j)\) 这一个因式。所以我们考虑将 \(f_i(x)\) 表示为 \(a \prod_{j \neq i}^n (x - x_j)\)

那么此时考虑将点 \(P_i(x_i,y_i)\) 带入 \(f_i(x)\) 得:

\[a = \dfrac{y_i}{\prod^n_{j \neq i} (x_i - x_j)} \]

\(a\) 带回原式得:

\[f_i(x) = y_i \prod^n_{j \neq i} \dfrac{x - x_j}{x_i - x_j} \]

既然已经有了所有的 \(f_i(x)\) 了,\(f(x)\) 就是 \(\sum^n_{i = 1} y_i \prod^n_{j \neq i} \dfrac{x - x_j}{x_i - x_j}\)

那么对于本题 \(\mathrm O(n^2)\) 就能过了。

code:

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int maxn = 2e3 + 10;
const int mod = 998244353;

int qpow(int a,int b)
{
    int res = 1;
    while(b)
    {
        if(b & 1)res = res * a % mod;
        a = a * a % mod;b >>= 1;
    }
    return res;
}
int n,k,x[maxn],y[maxn];
int f(int k)
{
    int ans = 0;
    for(int i = 1;i <= n;i++)
    {
        int p = 1,q = 1;
        for(int j = 1;j <= n;j++)if(i != j)p = p * (k - x[j]) % mod,q = q * (x[i] - x[j]) % mod;
        ans = (ans + p * qpow(q,mod - 2) % mod * y[i] % mod) % mod;
    }
    return (ans % mod + mod) % mod;
}

signed main()
{
    cin >> n >> k;
    for(int i = 1;i <= n;i++)cin >> x[i] >> y[i];
    cout << f(k);
    return 0;
}

那么假如我们要插入一些点呢?但是我们注意到每次新加入一个点的时候要重新插值,如果要多次增加点,那么我们不就炸了吗?

此时我们再次回看此前的式子:

\[f(x) = \sum^n_{i = 1}y_i \prod^n_{j \neq i} \dfrac{x - x_j}{x_i - x_j} \]

考虑设 \(g = \prod^n_{i = 1}(x - x_i)\),则 \(f_i(x)\) 就被我们化为了:

\[f_i(x) = g \sum_{i=1}^n\prod^n_{i \neq j} \dfrac{y_i}{(x - x_i)(x_i - x_j)} \]

那么此时设 \(t_i = \dfrac{y_i}{\prod^n_{j \neq i}(x_i - x_j)}\)。则:

\[f(x) = g\sum^n_{i = 1}\dfrac{t_i}{k - x_i} \]

然而你发现你对于一个新加入的点,你只需要求出 \(t_i\) 即可。一次是 \(\mathrm O(n)\) 的。那么加入 \(n\) 个点,我们在任何时间去查询 \(f(x)\) 都是 \(\mathrm O(n^2)\) 的。

posted @ 2025-07-26 07:57  sqrtqwq  阅读(6)  评论(0)    收藏  举报