模板 拉格朗日插值法

2022-05-07 22:27:15 字數 3279 閱讀 9388

update:其實拉格朗日插值法的問題在於求分母的複雜度是 \(o(n^2)\) 的,要是還要求逆元則再多乙個 \(logp\) 變成 \(o(n^2logp)\),但是當乙個多項式要重複使用的時候,也不必求出他的各個係數,只要預處理出各項分母的逆元之後,\(o(nlogp)\) 處理分子(求出字首積和字尾積),然後再插值,漸進複雜度和求出係數值的一樣。當分母是等差數列之類的有規律的東西,他的分母可能是可以更快求出的。

參考資料:

因為高斯消元法是n立方的,有些鬼畜問題需要n平方的拉格朗日插值法。

使用逆元的n平方logn預處理,nlogn單次詢問的重心拉格朗日插值法:

(假如使用double的話,理論上預處理和詢問都少個log)

#includeusing namespace std;

typedef long long ll;

namespace lagrange_interpolation_polynomial

return ans;

}void init_xi_xj()}}

for(int i=1;i<=n;i++)}}

void init_k(int k)

}inline int prod(int i,int k)

int lagrange(int k)

return ans;

}}using namespace lagrange_interpolation_polynomial;

int main()

init_xi_xj();

printf("%d\n",lagrange(k));

}

通過n個不同的點直接構造出多項式。

$f(x)=\sum\limits_^ y_i \prod\limits_\frac $

正確性:代入 \(x_i\) 只有 \(y_i\) 右邊是1,其他分子都有0,消掉了。

那麼可以n平方構造。

需要小心溢位以及卡常數。假如進行同乙個多項式的多次求 \(f(k)\) 的值 ,\(x_i-x_j\) 的逆元需要多次使用,可以像下面的類似做法預處理他們的差,當然kd和pkd要重新處理。不需要用map存,這樣和直接求qpow乙個鬼樣。

開個invd陣列,儲存每兩個項之間的差的逆元。

注意到prod裡面有一項是 \(k-x_j\) 的積,這裡也可以選擇直接記錄這個積。畢竟模運算比較費時,卡出來的常數可能差幾倍

因為是要求逆元的,所以預處理 \(o(n^2logn)\) 。

然後每次求新k時,預處理重心拉格朗日插值法的g, \(o(nlogn)\) 。

多次求同一多項式的值快了不少的,比原版的拉格朗日插值。就是要 \(o(n^2)\) 的額外空間。

先卡掉重複求差的逆元的,已經可以通過了。

#includeusing namespace std;

typedef long long ll;

const int mod=998244353;

int n,x[2005],y[2005];

int qpow(int x,int n)

return ans;

}int invd[2005][2005];

int kd[2005];

void init_prod(int k)

return ans;

}int invd[2005][2005];

int kd[2005],pkd;

void init_prod(int k)

return ans;

}void init_xi_xj()}}

for(int i=1;i<=n;i++)}}

void init_k(int k)

}inline int prod(int i,int k)

int lagrange(int k)

return ans;

}}using namespace lagrange_interpolation_polynomial;

ll jury(ll x) ;

ll ret=0;

ll tx=1;

for(int i=0; i<=10; i++)

//cout<<"jury: "《一般我們代入的點都是連續自然數,當 \(x_i\) 的取值是連續自然數時,插值法因為分母變得容易處理而變成n複雜度。

以從0開始取舉例。

假設當前n為4,從1開始取。其實分子無論怎麼取值都是可以用字首積和字尾積預處理出來的,然後兩段乘在一起。關鍵是分母,當分母是連續自然數的時候不必兩兩枚舉。

\(y_1\frac+y_2\frac+y_3\frac+y_4\frac\)

分母是:\(1*(-1)(-2)(-3),(1)*(-1)*(-2),(2)(1)*(-1),(3)(2)(1)\)

也就是前面階乘,後面是負數的階乘,負數的階乘也很好想,比如這裡n=4,那麼第一項有3個負數,階乘為負數,第二項為正數,第三項為負數……也就是n-i為奇數的項是負數。

可不斷插點的重心拉格朗日插值法。

原式$f(x)=\sum\limits_^ y_i \prod\limits_\frac $

把分子補上缺的項,提出來,記 \(g=\prod\limits_^ x-x_i\)

$f(x)=g\sum\limits_^ \frac \prod\limits_\frac $

再記 \(h_i= \prod\limits_\frac\)

$f(x)=g\sum\limits_^ \frac $

那麼每次多加乙個點的時候,更新 \(g\) 以及每乙個 \(h_i\) 就可以了。

經典例題:求 $\sum\limits_^ i^k $ n很大但k只有幾千萬(需要連續字首優化)

推出計算式之後,就是計算上面那個東西。注意步驟,首先要確定多項式的係數,乙個k次多項式的和一般都是k+1次的,這裡是m+1次多項式的和,也就是m+2次多項式,需要m+3個點。

注意用拉格朗日插值時,判斷k與x_i不重複再插,不然返回y_i就可以了。

#includeusing namespace std;

typedef long long ll;

const int mod=1e9+7;

namespace lagrange_interpolation_polynomial

return ans;

}void init_xi_xj()}}

for(int i=1;i<=n;i++)

//cout<<"pinvd["int main()

n-=vm[0];

vm=tv;

}cout<}

}

拉格朗日插值法

拉格朗日插值法 拉格朗日插值法可以幫助我們解決以下的問題 已知x取值0,1,1,2時,f取值2,2,0,6 求x 3時f的值。示例1 intxs intys f 3 intval lagrangepolynomial 3,xs,ys staticint lagrangepolynomial intx...

拉格朗日插值法

模板題 給出n nn個點 xi yi x i,y i xi y i 讓你確定這個n 1 n 1n 1次方程並代入求值 這個有三種求法 第一種是差分法,只適用於xi ix i i xi i的情況,就是不斷做差分直到序列變成乙個定值就可以求出所有項的係數,複雜度o n 2 o n 2 o n2 第二種是...

拉格朗日插值法

function p lagrange x,y p lagrange x,y 其中x和y是向量,p是返回的多項式向量 m獲取x的個數 m length x for k 1 1 m 表示乙個插值函式的起始值 v 1 for i 1 1 m if k i 注意 以後凡是在遇到乙個在數學上是 x 1 等包...