浅谈拉格朗日插值法
模板题链接:P4781 【模板】拉格朗日插值
题意:
给定 $n$ 个点 $P_i(x_i,y_i)$ ,将过该 $n$ 个点的最多 $n-1$ 次多项式记为 $f(x)$
给出 $k$ ,求 $f(k) \bmod 998244353$
证明:过 $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$ 代入 $g_i(x)$ 得
故
把 $k$ 代入即可得
求解时可以先分别求出分子和分母,最后分子乘上分母的逆元即可
代码:
#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;
}