拉格朗日差值公式:
-
拉格朗日插值法
這道題。。
在以后的日常生活中,我們有些人在給機器編程的過程中可能會遇到一些模型中的函數,不能用實際的代數,或者機器的數據來准確的模擬這個函數的表達(比如sinx,這個函數的准確值的求法着實讓人摸不着頭腦。),sinx很抽象,但是我們完全可以在sinx上多取很多點,使得用多項式能夠近似表達。而多項式可以帶入數據准確的求得其函數值。
如果你要用機器加工一個外形波浪(sinx)的零件,你完全可以按照拉格朗日插值法求得一個多項式來近似表達它的外形,從而加工出光滑的波浪表面。
在其他方面應用也很廣泛。
開始學習:
眾所周知,n個二維坐標系上的不同的點能夠確定唯一一個最高次為n-1多項式。
有些題需要或者需要類似的知識。
引入拉格朗日插值公式:
拉格朗日插值公式就是根據給你的點來O(n^2)求那個多項式的系數。
根據帶入的點,我們可以得到這樣一種方案:
每一個點“掌管”多項式的一部分,多項式由n部分組成,當帶入一個點的橫坐標xi時,其他的部分中都帶有(x-xi)這一個因式使得其值為0,最后xi“掌管”的那部分中沒有這個因式使得這一部分的值為(xi,yi)中的yi。
根據這個原則,帶入所有的點的橫坐標都滿足縱坐標等於其對應的值,我們找到了那個多項式。
f(xk)表示取第k個x值時它所對應的那一部分的值。
(圖片來源luogu)
可以感知到,當x取xi之外的值時,k-x[j]肯定有一項為0,進而約去整個部分。
當然,取這些x之外的值的時候所有部分一起發揮作用,而不是約去。
關於其進階:
拉格朗日在x取值連續的時候可以被優化成連乘的形式進行O(n)求解。這里不再深入講述,真正深入研究者們可以瀏覽其他dalao博客自行學習。
例題P4781 拉格朗日插值:
裸板子題,O(n^2)求解。
代碼:
#include<cstdio> #include<cstring> #include<iostream> #define modd 998244353 #define ll long long #define N 2003 ll read() { ll ans=0; char ch=getchar(),last=' '; while(ch<'0'||ch>'9')last=ch,ch=getchar(); while(ch>='0'&&ch<='9')ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); return last=='-'?-ans:ans; } ll n,k,x[N],y[N],ans; ll ksm(ll now,ll ur) { ll anss=1; while(ur>0) { if(ur&1)anss=anss*now%modd; now=(now*now)%modd; ur>>=1; } return anss; } int main(){ n=read(),k=read(); for(int i=1;i<=n;i++) x[i]=read(),y[i]=read(); for(int i=1;i<=n;i++) { ll up=1,down=1; for(int j=1;j<=n;j++) { if(i==j)continue; up=(up*(k-x[j]+modd)%modd)%modd; down=(down*(x[i]-x[j]+modd)%modd)%modd; } ans=(ans+y[i]*up%modd*ksm(down,modd-2)%modd)%modd;//除法取模不能直接模,求逆元 } printf("%lld",ans); return 0; }
完結。希望對各位的學習有所幫助。
