[学习笔记]拉格朗日&重心拉格朗日插值法

〇、前言 ¶

鸽了好久了,于 2021/4/5 看到重心 Lagrange 插值法,惊讶于 O(n) 的快速插值,想要把这篇完善一下。

壹、普通 Lagrange 插值法 ¶

对于一个 k 次多项式 f(x),假如我们已经知道其中 k+1 个点的坐标 (xi,yi),那么我们并不需要知道这个多项式的系数(其实也是可解的)而直接求任意一个 x 对应的坐标。

假设我们已知 k+1(xi,yi),现在我们要求 x 所对应的 y,有

y=i=0kyij=0,jikxxjxixj

直接求得 y 咯。

当然,如果你想要联立 k+1 个多项式高斯消元解出 f,再求 f(x),这也是可以的 但是似乎拉格朗日比高斯消元好记

求原函数或单点差值均 O(n2).

贰、重心 Lagrange 插值法 ¶

考虑我们的插值法计算了很多重复的部分,不妨把式子变个型:

y=i=0kyij=0,jikxxjxixj=i=0kyij=0,jik(xxj)p=0,pik1xixp=i=0kj=0,jik(xxj)p=0,pikyixixp=j=0k(xxj)(i=0kyip=0,pik(xixp)×1xxi)

最后一步的变形,为了让 脱离 i 的限制,补上了一个 1xxi,再在后面乘上分数。

稍微整理一下,若

l(x)=Δi=0k(xxi)wi=Δyip=0,pjk(xixj)

那么最后,得到差值过程:

y=l(x)i=0kwixxi

预处理仍然是 O(n2),但是单次差值变成 O(n),求原函数仍然是 O(n2).

叁、参考代码 ¶

还没有时间打重心 lagrange 的插值法,目前只打了 O(n2) 的。

模板连接

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long ll;
template<class T>inline T readin(T x){
	x=0; int f=0; char c;
	while((c=getchar())<'0' || '9'<c) if(c=='-') f=1;
	for(x=(c^48); '0'<=(c=getchar()) && c<='9'; x=(x<<1)+(x<<3)+(c^48));
	return f? -x: x;
}

const int maxn=2000;
const int mod=998244353;

inline int qkpow(int a, int n){
	int ret=1;
	for(; n>0; n>>=1, a=1ll*a*a%mod)
		if(n&1) ret=1ll*ret*a%mod;
	return ret;
}

int x[maxn+5], y[maxn+5], n, k;

inline void input(){
	n=readin(1), k=readin(1);
	for(int i=1; i<=n; ++i)
		x[i]=readin(1), y[i]=readin(1);
}

inline void getval(int k){
	int ans=0;
	for(int i=1; i<=n; ++i){
		int up=1, down=1;
		for(int j=1; j<=n; ++j) if(j!=i){
			up=1ll*up*(k-x[j])%mod;
			down=1ll*down*(x[i]-x[j])%mod;
		}
		ans=(ans+1ll*y[i]*up%mod*qkpow(down, mod-2)%mod)%mod;
	}
	printf("%d\n", (ans+mod)%mod);
}

signed main(){
	input();
	getval(k);
	return 0;
}
posted @   Arextre  阅读(1913)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示