拉普兰德 拉格朗日差值法,它可以通过(n)个点来构造出一个(n-1)次多项式(f(x))(恩。应该是最多(n-1)次,因为有些高次项的系数可能是(0))。
8说了。。。康题:P4781 【模板】拉格朗日插值
题意:给(n)个点((x_1,y_1),dots,(x_n,y_n)),你要构造出一个多项式(f(x)),使得(forall 1le i le n,f(x_i) = y_i),再给一个(k),你需要输出(f(k))的值。
然后拉格朗日差值这个神仙东西就横空出世了~
它的想法就是我是否能构造出(n)个多项式(ell_1(x),ell_2(x),dots,ell_n(x)),使得(forall 1le i le n),有
(对其他的(x)并没有要求)
那么结论就是显然可以,并且
这个显然是对的吧!
当(x = x_i)时,(frac{x - x_j}{x_i - x_j} = frac{x_i - x_j}{x_i - x_j} = 1),所以后面的所有因式都是(1),他们的乘积自然也是(1)。
当(x = x_k (k ot= i))(em...这里的(k)和题面上的不是同一个人),显然会有一个不等于(i)的(j),使得(x_k - x_j = 0),换句话说会有一个因式满足(frac{x - x_j}{x_i - x_j} = 0)。
然后再看回来,既然我们构造出了(ell_{i}(x)),那么(f(x))很好构造吧
根据(ell_{i}(x))的性质,容易验证(f(x_1) = y_1, f(x_2) = y_2,dots,f(x_n) = y_n)。
妙啊~~
好,然后看一下板子题的范围(1 le n le 2 imes 10^3),恩,直接把(k)代进去,算就完了,复杂度$ O(n^2)$
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int P=998244353;
inline int fpow(int a,int b){
int ret=1; for (;b;b>>=1,a=1ll*a*a%P) if (b&1) ret=1ll*ret*a%P;
return ret;
}
#define normal(x) (((x)%P+P)%P)
#define inv(x) (fpow((x),P-2))
const int N=2010;
int lagrange(int *x,int *y,int n,int k){
int ans=0;
for (int i=1;i<=n;i++){
ll tmp=y[i]%P;
for (int j=1;j<=n;j++) if (j!=i)
tmp=1ll*tmp*inv(normal(x[i]-x[j]))%P*normal(k-x[j])%P;
ans=(ans+tmp)%P;
}
return ans;
}
int x[N],y[N],K,n;
int main(){
scanf("%d%d",&n,&K);
for (int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
printf("%d
",lagrange(x,y,n,K));
return 0;
}