1. 程式人生 > >淺談算法——拉格朗日插值

淺談算法——拉格朗日插值

bubuko 讀者 其中 inf 最好 log nom rac 呵呵

拉格朗日插值法:是以法國十八世紀數學家約瑟夫·拉格朗日命名的一種多項式插值方法(摘自某度百科)

首先我們需要知道,拉格朗日插值法有何用?


舉例子永遠是最好的方法

比如說,已知下面這幾個點,我想找到一根穿過它們的曲線:

技術分享圖片

\(k+1\)個點是肯定可以確定一個\(k\)次函數的,因為待定系數法啊,然後我們假設函數為\(f(x)=a_0+a_1x+a_2x^2\),然後我們就有
\[ \begin{cases}y_1=a_0+a_1x_1+a_2x_1^2\nonumber\\y_2=a_0+a_1x_2+a_2x_2^2\nonumber\\y_3=a_0+a_1x_3+a_2x_3^2\nonumber\end{cases} \]


可是可以,但是擴展性不強……畢竟考場上沒有可以解多元一次方程的機子……手動推通解的話……呵呵

拉格朗日也是這樣想的,但是他覺得:我可以通過三根二次曲線相加得到這個函數,那麽是怎樣的三根曲線嘞?

第一根曲線\(f_1(x)\),滿足\(f_1(x_1)=1,f_1(x_2)=f_1(x_3)=0\)

技術分享圖片

然後第二、三根曲線類似

技術分享圖片

技術分享圖片

我們可以發現

  • \(y_1f_1(x)\)可以保證,在\(x_1\)處,取值為\(y_1\),其余兩點取值為0
  • \(y_2f_2(x)\)可以保證,在\(x_2\)處,取值為\(y_2\),其余兩點取值為0
  • \(y_3f_3(x)\)可以保證,在\(x_3\)處,取值為\(y_3\)
    ,其余兩點取值為0

那麽
\[ f(x)=y_1f_1(x)+y_2f_2(x)+y_3f_3(x) \]
可以一一穿過這三個點

技術分享圖片

當函數不是二次,而是多次的時候,這個方法同樣成立

於是前人根據這個方法,總結出了拉格朗日插值法的一般式,即
\[ f(x)=\sum\limits_{i=0}^ky_i\prod\limits_{j\not =i}\dfrac{x-x_j}{x_i-x_j} \]
(因為1~k+1寫起來很醜,所以這裏寫的是0~k,本質相同)

我們可以發現,任意代入一個\(x_k\),都必然有\(f(x_k)=y_k\),過程留給讀者自己推導

這樣我們就可以在\(O(k^2)\)的時間內求出\(f(x)\)


我們再來考慮一些特殊的情況,比如\(x_i\)連續的情況

我們先把式子抄一遍
\[ f(x)=\sum\limits_{i=0}^ny_i\prod\limits_{j\not =i}\dfrac{x-x_j}{x_i-x_j} \]
由於\(x_i\)連續,所以我們可以把分子用前後綴積來表示
\[ P_i=\prod\limits_{j=0}^i(x-x_j),S_i=\prod\limits_{j=i}^n(x-x_j) \]
然後分母可以寫成階乘的形式,式子變成
\[ f(x)=\sum\limits_{i=0}^ny_i\dfrac{P_{i-1}·S_{i+1}}{(-1)^{n-i}i!(n-i)!} \]
那麽我們就可以在\(O(k)\)的時間內算出\(f(x)\)的值了


至於一些應用,最常見的就是求\(\sum\limits_{i=1}^ni^k\)的值,也就是求冪和,根據這裏的式子可以得到
\[ S_k(n)=\sum\limits_{i=1}^ni^k=\dfrac{(n+1)^{k+1}-\sum\limits_{j=0}^{k-1}\binom{k+1}{j}S_j(n)-1}{k+1} \]
容易發現其為\(k+1\)次多項式,於是我們可以使用拉格朗日插值法

其中\(i\in[0,k+1]\)的取值我們用線篩,對於每個素數我們暴力快速冪,這部分時間復雜度為\(O(\dfrac{k}{\ln k}·\log k)=O(k)\)

所以總時間復雜度為\(O(k)\)

淺談算法——拉格朗日插值