插值:
已知平面直角坐标系上的\(n\)个点,找出一个函数\(f(x)\)过这\(n\)个点,这样的函数有无限多个。
拉格朗日插值:
首先他构造了\(n\)个函数,第\(i\)个是\(f_i(x)=\left\{\begin{matrix}
y_i & x=x_i\\
0 & x=x_j(j\ne i)
\end{matrix}\right.\)。对于其余的\(x\),我们并不关心。
这样我们可以得出$f_i(x)=\frac{y_i\times \prod_{j\ne i} (x-x_j)}{\prod_{j\ne i} (x_i-x_j)} $。
最终可以得出答案 \(f(x)=\sum_{i-1}^n f_i(x)\)。
例题:
abc137F
代码:
#include<iostream>
#define int long long
using namespace std;
int p;
int a[3010];
int b[3010];
int c[3010];
int d[3010];
int ksm(int x,int y){
int ans=1;
while(y){
if(y%2==1){
ans=ans*x%p;
}
x=x*x%p;
y/=2;
}
return ans;
}
int inv[3010];
signed main(){
cin>>p;
for(int i=1;i<p;i++){
inv[i]=ksm(p-i,p-2);
}
for(int i=0;i<p;i++){
cin>>a[i];
}
b[0]=1;
for(int i=0;i<p;i++){
for(int j=p;j>=0;j--){
b[j]=b[j]*(p-i)%p;
if(j!=0){
b[j]=(b[j]+b[j-1])%p;
}
}
}
c[0]=1;
for(int i=1;i<p;i++){
for(int j=p-1;j>=0;j--){
c[j]=c[j]*(p-i)%p;
if(j!=0){
c[j]=(c[j]+c[j-1])%p;
}
}
}
int k=1;
for(int j=1;j<p;j++){
k=k*(p-j)%p;
}
k=ksm(k,p-2)*a[0]%p;
for(int j=0;j<p;j++){
d[j]=(d[j]+c[j]*k)%p;
}
for(int i=1;i<p;i++){
for(int j=0;j<p;j++){
c[j]=b[j];
}
for(int j=0;j<p;j++){
c[j]=c[j]*inv[i]%p;
if(j!=p-1){
c[j+1]=(c[j+1]-c[j]+p)%p;
}
}
k=1;
for(int j=0;j<p;j++){
if(i!=j){
k=k*(i-j+p)%p;
}
}
k=ksm(k,p-2)*a[i]%p;
for(int j=0;j<p;j++){
d[j]=(d[j]+c[j]*k)%p;
}
}
for(int i=0;i<p;i++){
cout<<d[i]<<" ";
}
return 0;
}
标签:拉格朗,插值,3010,ne,int,ans
From: https://www.cnblogs.com/z-2-we/p/18072044