问题
给定 \(n\) 个点,确定一个多项式 \(f(x)=\sum_{i=0}^{n-2}a_ix^i\)。求 \(f(k)\)。
解法
拉格朗日插值的核心思想是通过构造 \(n\) 个函数,满足第 \(i\) 个函数经过 \((x_1,0),(x_2,0),\cdots,(x_i,y_i),\cdots,(x_n,0)\),将这 \(n\) 个函数的系数累加即可得到原函数。
具体地,有\(f_i(x)= y_i \prod_{i \not = j} \frac{x-x_j}{x_i-x_j}\)。
故原函数
\[\begin{aligned} f(x)=\sum_{i=1}^{n}y_i \prod_{i \not = j} \frac{x-x_j}{x_i-x_j} \end{aligned} \]那么将原问题的 \(k\) 代入得:
\[\begin{aligned} f(k)=\sum_{i=1}^{n}y_i \prod_{i \not = j} \frac{k-x_j}{x_i-x_j} \end{aligned} \]这样就在 \(\Theta(n^2)\) 的时间求得一个多项式的值。
练习
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
w=(w<<1)+(w<<3)+(ch^48);
ch=getchar();
}
return w*f;
}
void write(int x)
{
if(x<0) x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int mod=998244353;
const int maxn=2e3+10;
int n,k;
int x[maxn],y[maxn];
int qpow(int a,int b,int mod)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
signed main()
{
n=read(),k=read();
for(int i=1;i<=n;++i)
{
x[i]=read(),y[i]=read();
}
int ans=0;
for(int i=1;i<=n;++i)
{
int fz=1,fm=1;
for(int j=1;j<=n;++j)
{
if(j!=i)
{
(fz*=(k-x[j]+mod)%mod)%=mod;
(fm*=(x[i]-x[j]+mod)%mod)%=mod;
}
}
(ans+=fz*qpow(fm,mod-2,mod)%mod*y[i])%=mod;
}
cout<<ans<<endl;
return 0;
}
标签:总结,拉格朗,ch,插值,res,int,aligned,mod
From: https://www.cnblogs.com/vanueber/p/18675630