「笔记」拉格朗日插值

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

给你 \(n\) 个点 \((x_i, y_i)\),将过这 \(n\) 个点的最多 \(n-1\) 次的多项式记为 \(f(x)\),求 \(f(k)\) 的值。

  • 方法 1:待定系数法

\(f(x) = \displaystyle\sum_{i=1}^{n-1}a_x x^i\) ,将每个 \(x_i\) 代入 \(f(x)\),有 \(f(x_i) = y_i\),这样就可以得到由 \(n\)\(n\) 元一次方程所组成的方程组,然后使用 高斯消元 解该方程组的每一项 \(a_i\),就得到了 \(f(x)\) 的表达式。

时间复杂度 \(\mathcal O(n^3)\)

  • 方法 2:拉格朗日插值法

题目要求构造一个函数 \(f(x)\) 过所有点 \(P_i(x_i, y_i)\)。设第 \(i\) 个点在 \(x\) 轴上的投影为 \(P_i^{\prime}(x_i, 0)\)

考虑构造 \(n\) 个函数 \(f_1(x),f_2(x),...,f_n(x)\),使得对于第 \(i\) 个函数 \(f_i(x)\) ,其图像过 \(\begin{cases}P_j^{\prime}(x_j, 0),(j \not = i) \\ P_i(x_i, y_i) \end{cases}\),则可知题目所求函数 \(f(x) = \displaystyle\sum_{i=1}^{n} f_i(x)\)

那么可以设 \(f_i(x) = a \times \prod_{j \not = i}(x - x_j)\),将点 \(P_i(x_i, y_i)\) 代入可以知道 \(a = \frac{y}{\prod_{j \not - i} (x - x_j)}\),所以

\[f_i(x) = y_i \times \frac{\prod_{j \not = i}(x - x_j)}{\prod_{j \not = i}(x_i - x_j)} = y_i \times \prod_{j \not = i} \frac{x - x_j}{x_i - x_j} \]

那么我们就可以从另外一个角度推导出通常意义下(而非模意义下)拉格朗日插值的式子为:

\[f(x) = \sum_{i=1}^{n} y_i \times \prod_{j \not = i} \frac{x - x_j}{x_i - x_j} \]

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 998244353;
const int MAXN = 1e5 + 10;

int n, K, ans = 0;
int x[MAXN], y[MAXN];

int read() {
    int s = 0, f = 0;
    char ch = getchar();
    while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while(isdigit(ch)) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return f ? -s : s;
}

int Pow(int x, int p) {
    int res = 1;
    while(p) {
        if(p & 1) res = res * x % mod;
        x = x * x % mod, p >>= 1; 
    }
    return res;
}

int Inv(int x) { return Pow(x, mod - 2); }

signed main() {
    n = read(), K = read();
    for(int i = 1; i <= n; ++i) {
        x[i] = read(), y[i] = read();
    }
    for(int i = 1; i <= n; ++i) {
        int fz = 1, fm = 1;
        for(int j = 1; j <= n; ++j) {
            if(i == j) continue;
            fz = fz * (K - x[j]) % mod;
            fm = fm * (x[i] - x[j]) % mod;
        }
        ans = (ans + y[i] * fz % mod * Inv(fm) % mod) % mod;
    }
    ans = (ans + mod) % mod;
    printf("%lld\n", ans);
    return 0;
}

另一个例题:

AtCoder ABC208 F - Cumulative Sum

题解

posted @ 2022-01-07 22:17  Suzt_ilymtics  阅读(131)  评论(0编辑  收藏  举报