[浅谈] 拉格朗日插值

发布时间 2023-06-07 16:05:00作者: FJOI

Introduce

给定 \(n\) 个点,那么可以确定一个不超过 \(n-1\) 项的多项式函数值。我们可以使用高斯消元,但是 \(O(n^3)\) 的时间复杂度和精度误差难以接受。

Principle

我们考虑构造函数 \(fi\) ,满足其在 \(x=x_i\) 时函数值为 \(1\) ,在 \(x=x_j(j\neq i,j\in[1,n])\)\(0\),这很好构造: $fi(x)=\prod_{j\neq i}\frac{x-x_j}{x_i-x_j} $ 。

然后再构造 \(f(x)=\sum_{i=1}^{n}y_ifi(x)\) ,那么这个函数就经过这 \(n\) 个点。

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

\(\text{P4781 【模板】拉格朗日插值}\)

给定 \(n\) 点确定多项式,求 \(f(k)\) ,直接代入上面的公式。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+110,mod=998244353;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
int n,k,x[N],y[N],ans;
int ksm(int x,int y){
	int sum=1;
	while(y){
		if(y&1)sum=(sum*x)%mod;
		y>>=1;
		x=(x*x)%mod;
	}
	return sum%mod;
}
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 tmp=y[i];
		for(int j=1;j<=n;j++)if(j!=i)tmp=tmp%mod*(k-x[j])%mod*ksm(x[i]-x[j],mod-2)%mod;
		ans=(ans+tmp)%mod;
	}
	printf("%lld\n",(ans+mod)%mod);
	return 0;
}