题目
题目链接:https://www.luogu.com.cn/problem/P4781
由小学知识可知 (n) 个点 ((x_i,y_i)) 可以唯一地确定一个多项式 (y = f(x))。
现在,给定这 (n) 个点,请你确定这个多项式,并求出 (f(k) mod 998244353) 的值。
(1 le n leq 2 imes 10^3),(1 le x_i,y_i,k < 998244353),(x_i) 两两不同。
思路
给出一个 (n) 次多项式的点值,拉格朗日插值法可以在 (O(n^2)) 的时间内求出该多项式 (f(k)) 的值。
为了插出该多项式,拉格朗日插值的思路是对每一个点值构建一个拉格朗日基本多项式,使得将 (x_1sim x_n) 带进去只有 (x_i) 的函数值是 (1),其余均为 (0)。
先不考虑如何构建多项式使得只有 (x_i) 带进去非 (0)。因为 (x_i) 两两不等,所以可以考虑如下多项式
[prod_{j
eq i}(k-x_j)
]
显然只有当 (k=x_i) 的时候非 (0)。为了让其值为 (1),可以给每一项都除以 (x_i-x_j),此时再带入 (k=x_i) 多项式的值就是 (1cdot 1cdot 1cdots=1)
所以说我们可以插出多项式
[f(k)=sum_{i=1}^{n}y_iprod_{j
eq i}frac{k-a_j}{x_i-x_j}
]
当我们带入 (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;
}