嘘~ 正在从服务器偷取页面 . . .

浅谈拉格朗日插值法


浅谈拉格朗日插值法

模板题链接P4781 【模板】拉格朗日插值

题意

给定 \(n\) 个点 \(P_i(x_i,y_i)\) ,将过该 \(n\) 个点的最多 \(n-1\) 次多项式记为 \(f(x)\)

给出 \(k\) ,求 \(f(k) \bmod 998244353\)

\[ f(k) = \sum\limits_{i=1}^{n}y_i\prod_{j\ne i}{ \dfrac{k-x_j}{x_i-x_j} } \]

证明:过 \(P_i\) 作垂线交 \(x\) 轴于 \(H_i(x_i,0)\)

构造 \(g_i(x),i=1,2,\cdots ,n\) ,使得 \(g_i(x)\) 的图像过 \(\begin{cases}P_i(x_i,y_i) \\[8pt] H_j(x_j,0),j\ne i\end{cases}\)

可以发现,\(g_i(x) = a \prod_{j\ne i}{(x-x_j)}\) ,其中 \(a\) 是未知数

因为 \(g_i(x)\)\(P_i(x_i,y_i)\) ,代入并整理可得

\[ a = \dfrac{y_i}{ \prod_{j\ne i}{(x_i-x_j)} } \]\(a\) 代入 \(g_i(x)\)\[ g_i(x) = y_i\times\dfrac{ \prod_{j\ne i}{(x-x_j)} }{ \prod_{j\ne i}{(x_i-x_j)} } = y_i\prod_{j\ne i}\dfrac{x-x_j}{x_i-x_j} \]\[ f(x) = \sum\limits_{i=1}^{n}g_i(x) = \sum\limits_{i=1}^{n}y_i\prod_{j\ne i}\dfrac{x-x_j}{x_i-x_j} \]

\(k\) 代入即可得

\[ f(k) = \sum\limits_{i=1}^{n}y_i\prod_{j\ne i}{ \dfrac{k-x_j}{x_i-x_j}} \]

求解时可以先分别求出分子和分母,最后分子乘上分母的逆元即可

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define gc() getchar()
#define pc(a) putchar(a)
#define mod (int)(998244353)
template<typename T>inline void read(T &k)
{
	char ch=gc();T x=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
	k=x*f;
}
template<typename T>inline void write(T k)
{
	if(k<0){k=-k;pc('-');}
	if(k>9)write(k/10);
	pc(k%10+'0');
}
#define MAXN (int)(2e3+5)
int qpow(int a,int b)
{
	int ans=1,base=a;
	while(b)
	{
		if(b&1)ans=ans*base%mod;
		base=base*base%mod;
		b>>=1;
	}
	return ans;
}
int inv(int x){return qpow(x,mod-2);}
int n,k,a,b,ans;
int x[MAXN],y[MAXN];
signed main()
{
	read(n);read(k);
	for(int i=1; i<=n; i++)
		read(x[i]),read(y[i]);
	for(int i=1; i<=n; i++)
	{
		a=y[i]%mod,b=1;
		for(int j=1; j<=n; j++) if(i!=j)
		{
			b=(x[i]-x[j]+mod)%mod*b%mod;
			a=(k-x[j]+mod)%mod*a%mod;
		}
		ans=(ans+a*inv(b)%mod)%mod;
	}
	write(ans);pc('\n');
	return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录