拉格朗日插值浅谈

题目大意:

给你n个点$(x[i],y[i])$,请你用这n个点构造一个$n-1$次多项式$f(x)$,给定一个数$k$,求出$f(k)$的值. 

solution:

本题$n$的规模较小,是拉格朗日插值的模板题.拉格朗日插值的具体思路如下:

我们的目标是构造一个函数,使得对于所有的$i \in [1,n]$,有$f(x[i])=y[i]$,于是一个非常自然的想法便产生了:我们可以构造$n$个函数,使得$f_(x[i])=y[i],f_(x[j])=0(j\not= i)$,然后将这$n$个函数相加即可.那么,如何构造这$n$个函数呢?

下面我们来看一条神奇的式子,它将向我们展示如何构造这若干个函数

  \(f_{i}(x)=\frac{\Pi_{j\not=i}(x-x_{j})}{\Pi_{j\not=i}(x_{i}-x_{j})} \cdot y[i]\)

 手动带入分析可知,这个式子符合我们的要求.于是乎,接下来我们利用这个式子实现拉格朗日插值:

\(f(x)=\sum_{i=1}^{n}\frac{\Pi_{j\not=i}(x-x_{j})}{\Pi_{j\not=i}(x_{i}-x_{j})}\cdot y_{i}\)

将$\Pi_^(x-x_)$提出,我们可以得到最终的拉格朗日插值式:

\(f(x)=\Pi_{i=1}^{n}(x-x_{i})\cdot[\sum_{i=1}^{n}\frac{y_{i}}{(x-x_{i})\cdot\Pi{j\not=i}(x_{i}-x_{j})}]\)

此式复杂度为$O(n^{2})$

Code:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define R register
#define next kdjadskfj
#define debug puts("mlg")
#define mod 998244353
#define Mod(x) ((x%mod+mod)%mod)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writeln(ll x);
inline void writesp(ll x);
ll n,k;
ll Ans1,Ans2,ans;
ll x[2010],y[2010];
inline ll Qpow(ll _,ll __){ll ___=1;for(;__;__>>=1){if(__&1) ___*=_,___=Mod(___);_*=_,_=Mod(_);}return ___;}
inline ll inv(ll _){return Mod(Qpow(_,mod-2));}

int main(){
	writeln(sizeof(int));
	n=read();k=read();
	Ans1=1;
	for(R ll i=1;i<=n;i++){
		x[i]=read();y[i]=read();
		Ans1*=Mod(k-x[i]);
		Ans1=Mod(Ans1);
	}
	for(R ll i=1;i<=n;i++){
		ans=1;
		for(R ll j=1;j<=n;j++){
			if(j==i) continue;
			ans*=Mod(x[i]-x[j]);
			ans=Mod(ans);
		}
		ans*=(k-x[i]);
		ans=Mod(ans);
		Ans2+=Mod(y[i])*inv(ans);
		Ans2=Mod(Ans2);
	}
	writeln(Mod(Ans1*Ans2));
}
inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x);putchar(' ');}
inline void writeln(ll x){write(x);putchar('\n');}

猜你喜欢

转载自www.cnblogs.com/ylwtsq/p/13399318.html