拉格朗日插值法
给你(n + 1)个点((x,y)),希望你求出过这几个点的(n-1)次多项式。
朴素的想法是把该多项式每一项的系数作为未知数,然后把点代入多项式中求出很多个(n)元(1)次方程组。然后高斯消元,时间复杂度为(O(n^3))
我们要介绍的拉格朗日插值法本质上来说是一种构造法,而不是去根据点对来想办法求解。
思考:对于当前给出的(n+1)个点,若给你一个多项式(f_i(x)),该多项式满足当你代入(x_i)时,(f_i(x)=y_i),否则,(f_i(x)=0),那么我们是不是只要把这(n+1)个多项式相加起来就可以求出我们想要求的多项式了。
知道了这点后,我们开始构造这(n+1)个多项式,具体的,我们构造出的第(i)个多项式长的样子像这样:
(f_i(x) = y_iprod_{i eq j}frac{x-x_j}{x_i-x_j})
构造思想即是希望当你代入任何一个(x_j eq x_i)时,该多项式的某一因式为(0),当你代入(x_i)时,该多项式可分解为(y_i*1)。上述的多项式便由此得来。
然后,我们要求的总的多项式(f(x)=sum_{i=1}^{n}y_iprod_{i eq j}frac{x-x_j}{x_i-x_j})。
你可以把它拆开来求出每一项的系数,总时间复杂度为(O(n^2))。
模板题,已知(x)个点,再给你一个(k),求(x-1)次多项式的某一点的值(f(k))
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 30005
#define mod 998244353
long long co[maxn],xi[maxn],yi[maxn],n,k,ans = 0;
long long qpow(long long x,long long y) {
long long now = 1;
while (y) {
if (y & 1) (now *= x) %= mod;
(x *= x) %= mod;
y >>= 1;
}
return now;
}
int main() {
scanf("%lld%lld
",&n,&k);
for (int i = 1;i <= n;i++) scanf("%lld%lld",&xi[i],&yi[i]);
for (int i = 1;i <= n;i++) {
long long num = yi[i],num1 = 1;
for (int j = 1;j <= n;j++) {
if (i == j) continue;
(num *= ((k - xi[j] + mod) % mod)) %= mod;
}
for (int j = 1;j <= n;j++) {
if (i == j) continue;
(num1 *= ((xi[i] - xi[j] + mod) % mod)) %= mod;
}
(ans += num * qpow(num1,mod - 2) % mod) %= mod;
}
printf("%lld
",ans);
return 0;
}