题目
题目链接:https://www.luogu.com.cn/problem/P4781由小学知识可知 \(n\) 个点 \((x_i,y_i)\) 可以唯一地确定一个多项式 \(y = f(x)\)。
现在,给定这 \(n\) 个点,请你确定这个多项式,并求出 \(f(k) \bmod 998244353\) 的值。
\(1 \le n \leq 2\times 10^3\),\(1 \le x_i,y_i,k < 998244353\),\(x_i\) 两两不同。
思路
给出一个 \(n\) 次多项式的点值,拉格朗日插值法可以在 \(O(n^2)\) 的时间内求出该多项式 \(f(k)\) 的值。
为了插出该多项式,拉格朗日插值的思路是对每一个点值构建一个拉格朗日基本多项式,使得将 \(x_1\sim x_n\) 带进去只有 \(x_i\) 的函数值是 \(1\),其余均为 \(0\)。
先不考虑如何构建多项式使得只有 \(x_i\) 带进去非 \(0\)。因为 \(x_i\) 两两不等,所以可以考虑如下多项式
显然只有当 \(k=x_i\) 的时候非 \(0\)。为了让其值为 \(1\),可以给每一项都除以 \(x_i-x_j\),此时再带入 \(k=x_i\) 多项式的值就是 \(1\cdot 1\cdot 1\cdots=1\)
所以说我们可以插出多项式
当我们带入 \(x_i\) 时,多项式的函数值就是 \(0+0+\cdots+y_i+0+0+\cdots\)。这样我们就插出这个多项式了。
时间复杂度 \(O(n^2)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2010,MOD=998244353;
int n,k;
ll ans,x[N],y[N];
ll fpow(ll x,ll k)
{
ll ans=1;
for (;k;k>>=1,x=x*x%MOD)
if (k&1) ans=ans*x%MOD;
return ans;
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++)
scanf("%lld%lld",&x[i],&y[i]);
for (int i=1;i<=n;i++)
{
ll res1=1,res2=1;
for (int j=1;j<=n;j++)
if (i!=j)
{
res1=res1*(k-x[j])%MOD;
res2=res2*(x[i]-x[j])%MOD;
}
ans=(ans+res1*fpow(res2,MOD-2)%MOD*y[i])%MOD;
}
printf("%lld",(ans%MOD+MOD)%MOD);
return 0;
}