拉格朗日插值学习笔记

拉格朗日插值学习笔记

插值

什么是插值?插值是一种通过已知的、离散的数据点推算一定范围内的新数据点的方法。

插值的一般形式如下:

已知 n 个点 P1(x1,y1),P2(x2,y2),,Pn(xn,yn),求 n1 次多项式 f(x) 满足

f(xi)=yi ,i[1,n] .

初次学习时,可以理解为待定系数法求解析式。只不过解方程(即高斯消元)是 O(N3) 的,而插值可以在 O(N2) 的时间内计算。并且,插值可以求逆元。

拉格朗日插值

拉格朗日插值是众多插值方式中的一种。设第 i 个点 Pi(xi,yi)x 轴上的投影为 Pi(xi,0)人话:作垂直。

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

如此构造的原因:

每个 fi(x) 都需要过 Pi,但不能过 Pj (ji)。也就是在 xi 处点值为 yi,而在 Pj (ji) 处的值都为 0。这样构造出来的 fi(x) 全部加起来才能符合要求。

于是设

fi(x)=aji(xxj) ,

将点 Pi(xi,yi) 代入得

a=yiji(xixj) ,

fi(x)=yiji(xxj)ji(xixj)=yijixxjxixj .

所以最终

(1)f(x)=i=1n(yijixxjxixj) .

这个公式特别重要,你可以什么都不会,但只需要记住这个公式就可以做题了。要求 f(k) 的时候,直接将 k 代入上式中就行。

洛谷 P4781 【模板】拉格朗日插值

constexpr int MAXN=2005,MOD=998244353;
int n,k,x[MAXN],y[MAXN];
int power(int a,int b){
	int res=1;
	for(;b;a=a*a%MOD,b>>=1)
		if(b&1)
			res=res*a%MOD;
	return res;
}
void add(int&x,int y){
	x=x+y>=MOD?x+y-MOD:x+y;
}
int lagrange(int k){
	int res=0;
	for(int i=1,s1,s2;i<=n;++i){
		s1=y[i],s2=1;
		for(int j=1;j<=n;++j){
			if(i==j) continue;
			s1=s1*(k-x[j]+MOD)%MOD;
			s2=s2*(x[i]-x[j]+MOD)%MOD;
		}
		add(res,s1*power(s2,MOD-2)%MOD);
	}
	return res;
}

signed main(){
	n=read(),k=read();
	for(int i=1;i<=n;++i) x[i]=read(),y[i]=read();
	printf("%lld\n",lagrange(k));
	return 0;
}

xi 连续时的做法

例题:[CF622F] The Sum of the k-th Powers

题意:求

i=1nik(mod109+7) .

其中 1n1090k106

这道题的前半部分是证明原式是一个关于 nk+1 次多项式。证法不是我们关心的内容,我们只关心这道题的后半部分:x 取值连续时的拉格朗日插值。

插一个 k+1 次多项式需要 k+2 个点。我们先将 n,k+2 代入 (1) 式中的 x,n

f(n)=i=1k+2(f(i)jinnjninj) ,

由于 nf(n)连续取值都已知,所以直接代入所有的 ninj

f(n)=i=1k+2(f(i)jinjij)=i=1k+2[f(i)(j=1i1njij)(j=i+1k+2njij)]=i=1k+2f(i)niii(ni1)k+2i(1)k+2i=i=1mf(i)n!i!(ni)!(ni1)!(nm1)!(1)mi(mi)! , 其中 m=k+2=n!(nm1)!i=1mf(i)(1)mi(ni1)!i!(ni)!(mi)!=n!(nm1)!i=1mf(i)(1)mii!(ni)(mi)! .

所以

f(n)=n!(nm1)!i=1mf(i)(1)mii!(ni)(mi)! .

复杂度 O(mlogV),预处理逆元和 f(i) 即可做到 O(m)

实际上还有一种不用这么复杂的解决方案。将原式化为

f(n)=i=1mf(i)(1)miprei1×sufi+1(i1)!(mi)! .

其中

prei=j=1i(nj)sufi=j=in(nj)

这是利用了 ji(nj)=[j<i(nj)][j>i(nj)] 的原理。这种方法的复杂度也是 O(mlogV),预处理逆元和 f(i) 也可以做到 O(m)

#include<bits/stdc++.h>
#define int long long
using namespace std;
 
constexpr int MAXN=1e6+5,MOD=1e9+7;
int n,k,pre[MAXN],suf[MAXN],fac[MAXN];
int power(int a,int b){
	int res=1;
	for(;b;a=a*a%MOD,b>>=1)if(b&1)res=res*a%MOD;
	return res;
}
int lagrange(int k){
	pre[0]=suf[k+3]=fac[0]=1;
	for(int i=1;i<=k+2;++i) pre[i]=pre[i-1]*(n-i)%MOD;
	for(int i=k+2;i;--i) suf[i]=suf[i+1]*(n-i)%MOD;
	for(int i=1;i<=k+2;++i) fac[i]=fac[i-1]*i%MOD;
	int res=0;
	for(int i=1,y=0,s1,s2;i<=k+2;++i){
		y=(y+power(i,k))%MOD;
		s1=pre[i-1]*suf[i+1]%MOD;
		s2=fac[i-1]*((k-i)&1?-1:1)*fac[k+2-i]%MOD;
		res=(res+y*s1%MOD*power(s2,MOD-2)%MOD)%MOD;
	}
	return res;
}
 
signed main(){
	scanf("%lld%lld",&n,&k);
	printf("%lld\n",(lagrange(k)+MOD)%MOD);
	return 0;
}

重心拉格朗日插值

拉格朗日插值还有一种特殊情况,那就是动态加点,随时询问。例题:LOJ #165. 拉格朗日插值

在朴素做法中,加点是 O(1) 的,查询是 O(n2) 的,再乘上 O(n) 次询问,总体复杂度达到了 O(n3)。发现问题在于:加点太快了,查询太慢了。考虑平均这两种操作。

将原式变形

f(x)=i=1n(yijixxjxixj)=i=1nyi(ji(xxj)ki1xixk)=i=1n(ji(xxj)kiyixixk)=j=1n(xxj)(i=1nyiki(xixk)×1xxi) .

注意最后一步中,我们为了让最外层的 Π 脱离 i 的限制,在 Σ 里面又乘上了一个 1xxi

(x)=j=1n(xxj)wi=yiki(xixk)

则得到最终的式子:

f(x)=(x)i=1nwixxi .

在新增加一个点之后,我们只需 O(nlogV) 更新 wi;在询问时,(x) 只需 O(n) 计算,加上计算逆元的复杂度也是 O(nlogV)

constexpr int MAXN=3005,MOD=998244353;
int n,x[MAXN],y[MAXN],w[MAXN],cnt;
int power(int a,int b){
	int res=1;
	for(;b;a=a*a%MOD,b>>=1)if(b&1)res=res*a%MOD;
	return res;
}

signed main(){
	n=read();
	while(n--){
		int opt=read(),X=read();
		if(opt==1){
			int Y=read();
			x[++cnt]=X,y[cnt]=w[cnt]=Y;
			for(int i=1;i<cnt;++i){
				w[i]=w[i]*power(x[i]-x[cnt],MOD-2)%MOD;
				w[cnt]=w[cnt]*power(x[cnt]-x[i],MOD-2)%MOD;
			}
		}else{
			int s1=1,s2=0;
			for(int i=1;i<=cnt;++i)
				if(X==x[i]){
					write(y[i]);
					goto byby;
				}
			for(int i=1;i<=cnt;++i){
				s1=s1*(X-x[i])%MOD;
				s2=(s2+w[i]*power(X-x[i],MOD-2)%MOD)%MOD;
			}
			write((s1*s2%MOD+MOD)%MOD);
			byby:;
		}
	}
	return fw,0;
}
posted @   Laoshan_PLUS  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示