拉格朗日插值学习笔记

拉格朗日插值学习笔记

只是用来存放板子。。。

裸插值

不知道怎么证:

正在问老师,等回复

最新回复:该是啥值就是啥值吧

UPD 2020.5.18 : 来自黄队的解释:过n+1个点的n次多项式只有一个,构造在这n个点满足条件的多项式就行了。

\[f(k)=\sum_{i=0}^{n} y_{i} \prod_{i \neq j} \frac{k-x[j]}{x[i]-x[j]} \]


#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define ll long long
ll read(){
	ll x=0;int pos=1;char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
	return pos?x:-x; 
}
const int N = 2001; 
const ll mod = 998244353;
ll n,k;
ll x[N],y[N];
ll ksm(ll a,ll b){

	ll res=1;
	while(b){

		if(b&1) res=res*a%mod;
		a=a*a%mod;
		b>>=1;

	}
	return res;
}
ll ginv(ll a){
	return ksm(a,mod-2);
}
ll lag(){
	ll res=0;
	for(int i=1;i<=n;i++){
		ll t1=1,t2=1;
		for(int j=1;j<=n;j++){

			if(i==j) continue;
			t1=t1*(k-x[j])%mod;

			t2=t2*(x[i]-x[j])%mod; 
		}
		res=(res+y[i]*t1%mod*ginv(t2)%mod+mod)%mod;
	}
	return res;
}
int main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++){
		x[i]=read();y[i]=read();
	}
	printf("%lld",lag());
	return 0;
}

连续插值

那么此时式子变为:

\[f(k)=\sum_{i=0}^{n} y_{i} \prod_{i \neq j} \frac{k-j}{i-j} \]

处理出

\[pre_i=\prod _{j=0} ^i k-j \]

\[suf_i=\prod _{j=i}^n k-j \]

分子:

\[pre_{i-1}*suf_{i+1} \]

分母:

\[fac[i]*fac[N-i]*(-1)^{N-i} \]

于是就可以\(nlogn\)了(逆元)

插值2

权当练习NTT了。。。

看到上面阶乘里面的i和n-i,是不是产生了什么想法?

具体地说,这就是一个卷积的形式

那么我们就可以用多项式乘法求出连续的一堆多项式的值了,时间复杂度从O(n)

实现

题解里蒯出来的

式子是这样的:

\[\sum_{i=0}^{n} f(i) \frac{(m+x) ! /(m+x-n-1) !}{(m+x-i)(-1)^{n-i} !(n-i) !} \]

然后卷出来往右平移n就行了(

posted @ 2019-12-02 20:37  lcyfrog  阅读(187)  评论(0编辑  收藏  举报