拉格朗日插值


拉格朗日插值定理

n个点值\((x_i,y_i) (1\leq i \leq n),\) 满足\(x_i \not=y_j(i\not= j)\),它们唯一确定一个\(n-1\)项多项式
\(f(x)=\sum_{i=1}^ny_i\prod_{j\not=i}\frac{x-x_j}{x_i-x_j}\)
对于此多项式,\(f(x_i)=y_i(i=1,2,···,n)\)

构造原理:

\(f(x)=f_1(x)+f_2(x)+···+f_n(x)\)
对于\(f_1(x)\)
\(f_1(x_1)=y_1,f_1(x_j)=0(j\not=1)\)
因此\(f_1(x)=A(x-x_2)(x-x_3)···(x-x_n)\)
\(f_1(x_1)=A(x_1-x_2)···(x_1-x_n)=y_1\)
所以\(A=\frac{y_1}{(x_1-x_2)(x_1-x_3)···(x_1-x_n)}\)

以此类推得到\(f(x)=\sum_{i=1}^ny_i\prod_{j\not=i}\frac{x-x_j}{x_i-x_j}\)

具体实现

  • 暴力实现:
    时间复杂度\(O(n^2)\)
点击查看代码
//洛谷模板
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define dul(p) (((p)%MOD+MOD)%MOD)
using namespace std;
const int maxn=1000000+10101;
const int MOD=998244353;
inline ll read(){
	ll x=0,f=1;char ch=getchar();
	for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
	for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-'0';
	return x*f;
}
ll ans,n,k,x[maxn],y[maxn];
ll power(ll x,ll y){
    ll ans=1;
	while(y){
	    if(y&1)ans=(ans*x)%MOD;
	    x=(x*x)%MOD;
	    y>>=1;
	}
	return dul(ans);
}
int 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++){
        ll a1=1,b1=1;
		for(int j=1;j<=n;j++){
			if(i==j)continue;
			a1=a1*(k-x[j])%MOD;
			b1=b1*(x[i]-x[j])%MOD;
		}
		ans=dul(ans+dul(y[i]*a1%MOD*power(b1,MOD-2)));
    }
    printf("%lld",dul(ans));
	return 0;
}


  • 特殊情况\(x_i=i\)
    \(f(x)=\sum_{i=1}^ny_i\prod_{j\not=i}\frac{x-x_j}{i-j}\)
    其中\(\prod (i-j)\)是一段连续数的乘积,可以预处理
    时间复杂度\(O(n)\)

应用

2.

FFT