拉格朗日插值

拉格朗日插值

首先,我们知道给出 n+1 个点 (xi,yi) 可以唯一确定一个 n 次多项式。

问题:给出 n+1 个点,求出这个 n 次多项式在 k 处的取值,即 f(k)

首先,我们可以列出 (n+1) 个方程解出这个多项式的系数,但是这样是 O(n3) 的。有没有更给力的?

实际上,我们有拉格朗日插值,可以在 O(n2) 的复杂度内解决这个问题。

构造多项式:

g(x)=i=0nyijikxixixj

我们说明这个多项式其实就是 f(x)

首先,g(x) 显然是一个 n 次多项式,我们只需说明 g(x)f(x)n 个位置处取值相同即可。

xk,ik,k,jixkxixixj=(jijkxkxixixj)×xkxkxkxj=0

xk,i=k,jixkxixixj=jixkxixkxj=1

因此

g(xk)=i=0nyijikxixixj=i=0k1yi×0+i=k+1nyi×0+yk×1=yk

g(x)f(x)x0,x1xn 处取值相等,因此,g(x)=f(x)

这样,我们就可以在 O(n) 的时间复杂度内求出 f(k) 的值了。

注意:在写的时候不要求 n2 次逆元,而是处理出来分母后再总共求 n 次,这样求逆元的总复杂度就是 O(nlogmod),不会成为瓶颈。

x 取值连续的时候,复杂度还可以优化。我们不妨设 xi=i,因为若 xii,由于满足取值连续,我们也可将图像整体平移。

g(x)=i=0nyijikxixixj

我们定义:

faci=j=1ijprei=j=0ikjsufi=j=inkj

那么,我们可以将 g(x) 改写为:

g(x)=i=0nyijikiij=i=0nyiprei1×sufi+1faci1×facni×(1)ni

预处理 fac,pre,suf 即可 O(n) 计算。

贴上代码:

#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
int n;
long long k,x[2010],y[2010]; 
long long fastpow(long long x,int y){
	long long ans=1;
	while(y){
		if(y&1) ans=(ans*x)%mod;
		x=(x*x)%mod;
		y>>=1;
	}
	return ans;
}
long long F(long long k){
	long long ans=0,a,b;
	for(int i=0;i<=n;i++){
		a=1,b=1;
		for(int j=0;j<=n;++j){
			if(i==j) continue;
			a=a*(k-x[j])%mod;
			b=b*(x[i]-x[j])%mod;
		}
		a=y[i]*a%mod*fastpow(b,mod-2);
		ans=(ans+a)%mod;
	}
	return (ans+mod)%mod;
}
int main()
{
	scanf("%d%lld",&n,&k);--n;
	for(int i=0;i<=n;i++) scanf("%lld%lld",&x[i],&y[i]);
	printf("%lld",F(k));
	return 0;
}
posted @   LiuLianLL  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示