原题链接:https://www.luogu.org/problemnew/show/P4781
拉格朗日插值
题目背景
这是一道模板题
题目描述
由小学知识可知, n n 个点 可以唯一地确定一个多项式。
现在,给定 n n 个点,请你确定这个多项式,并将 代入求值。
求出的值对 998244353 998244353 取模。
输入输出格式
输入格式:
第一行两个正整数 n,k n , k ,含义如题。
接下来 n n 行,每行两个正整数 ,含义如题。
输出格式:
一个整数表示答案
输入输出样例
输入样例#1:
3 100
1 4
2 9
3 16
输出样例#1:
10201
输入样例#2:
3 100
1 1
2 2
3 3
输出样例#2:
100
说明
n≤2000xi,yi,k≤998244353 n ≤ 2000 x i , y i , k ≤ 998244353
样例一中的三个点确定的多项式是 f(x)=x2+2x+1 f ( x ) = x 2 + 2 x + 1 ,将 100 100 代入求值得到 10201 10201 。
样例二中的三个点确定的多项式是 f(x)=x f ( x ) = x ,将 100 100 代入求值得到 100 100 。
如果你不会拉格朗日插值,你可以到这里去学习一下。
此外,请注意算法的常数问题,建议开启O2优化。
题解
所谓 lagrange l a g r a n g e 插值法核心就是下面的公式,我们可以通过这个公式求出唯一的一个 n−1 n − 1 阶多项式,使得多项式的函数图像经过给定的 n n 个点:
这个式子看起来非常复杂,实际上本质非常简明,设 g(x)=∏nj=1,j≠ix−xjxi−xj g ( x ) = ∏ j = 1 , j ≠ i n x − x j x i − x j ,就有 g(xj)=0,g(xi)=1 g ( x j ) = 0 , g ( x i ) = 1 ,实际上其他的 x x 都会被消掉,只有才有值,所以这个多项式表示的函数图像能经过给出的所有点。
唯一性的证明:通过待定系数法列出方程后,系数矩阵是范德蒙德矩阵,存在逆矩阵,因而解具有唯一性。
lagrange l a g r a n g e 插值法告诉我们: n n 个点可以确定一个唯一的项数不超过点数的多项式,这一点非常重要,这种用点描述多项式的形式称为多项式的点值形式,从点值变成系数式的过程称为插值。
对于这道题来说,我们就不需要一一算出每一项的系数,只需要把代入 f(x) f ( x ) ,按照公式枚举一下 i,j i , j 就能在 O(n2) O ( n 2 ) 的时间内算出 f(k) f ( k ) 的值。
代码
#include<bits/stdc++.h>
using namespace std;
const int M=2e4+5,mod=998244353;
int n,k,x[M],y[M];
void in(){scanf("%d%d",&n,&k);for(int i=1;i<=n;++i)scanf("%d%d",&x[i],&y[i]);}
int power(int a,int p){if(p==1)return a;int hh=power(a,p/2);return (p&1)?1ll*hh*hh%mod*a%mod:1ll*hh*hh%mod;}
int lagrange(int n,int k)
{
int ans=0,s1,s2;
for(int i=1;i<=n;++i)
{
s1=s2=1;
for(int j=1;j<=n;++j){if(i==j)continue;s1=1ll*s1*(k-x[j])%mod;s2=1ll*s2*(x[i]-x[j])%mod;}
ans=(ans+1ll*y[i]*s1%mod*power(s2,mod-2))%mod;
}
return ans<0?ans+mod:ans;
}
void ac(){printf("%d",lagrange(n,k));}
int main(){in();ac();}