「笔记」拉格朗日插值

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

给你 n 个点 (xi,yi),将过这 n 个点的最多 n1 次的多项式记为 f(x),求 f(k) 的值。

  • 方法 1:待定系数法

f(x)=i=1n1axxi ,将每个 xi 代入 f(x),有 f(xi)=yi,这样就可以得到由 nn 元一次方程所组成的方程组,然后使用 高斯消元 解该方程组的每一项 ai,就得到了 f(x) 的表达式。

时间复杂度 O(n3)

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

题目要求构造一个函数 f(x) 过所有点 Pi(xi,yi)。设第 i 个点在 x 轴上的投影为 Pi(xi,0)

考虑构造 n 个函数 f1(x),f2(x),...,fn(x),使得对于第 i 个函数 fi(x) ,其图像过 {Pj(xj,0),(ji)Pi(xi,yi),则可知题目所求函数 f(x)=i=1nfi(x)

那么可以设 fi(x)=a×ji(xxj),将点 Pi(xi,yi) 代入可以知道 a=yj−̸i(xxj),所以

fi(x)=yi×ji(xxj)ji(xixj)=yi×jixxjxixj

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

f(x)=i=1nyi×jixxjxixj

#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 @   Suzt_ilymtics  阅读(138)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2021-01-07 About me
点击右上角即可分享
微信分享提示