拉格朗日插值
拉格朗日插值定理
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<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#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)\)