拉格朗日插值法
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拉格朗日插值法相关的知识,希望对你有一定的参考价值。
拉格朗日插值法
重心拉格朗日插值法
gu
拉插板子
cal 离散点拉插 O ( n 2 ) O(n^2) O(n2)
inpo 连续点拉插 O ( n ) O(n) O(n)
//Lagrange Interpolation
#define il inline
il ll ksm(ll a,ll n,ll m=mod){ll s=1;while(n){if(n&1) s=s*a%m;a=a*a%m;n>>=1;}return s;}
struct LR{
ll x[N],y[N];int n;
ll fac[N+5],facinv[N+5],inv[mod+5];
il ll Inv(ll n){return ksm(n,mod-2);}
il void init(){ //预处理阶乘和阶乘逆元,逆元.
fac[0]=inv[0]=inv[1]=1;for(int i=1;i<=N;i++) fac[i]=fac[i-1]*i%mod;
facinv[N]=Inv(fac[N]);
for(int i=N-1;~i;i--) facinv[i]=facinv[i+1]*(i+1)%mod;
for(int i=2;i<mod+5;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
il ll cal(ll k){ //离散点n个点[0,n-1] x[i],y[i] 插f(k)
ll s=0;
for(int i=0;i<n;i++){
ll p=y[i]%mod,q=1;
for(int j=0;j<n;j++){
if(i==j) continue;
p=p*(k-x[j])%mod;
q=q*(x[i]-x[j])%mod;
}
s=(s+p*Inv(q)%mod)%mod;
}return (s%mod+mod)%mod;
}
il ll inpo(ll *f,int n,ll x){ //给定 连续i属于[0,n] f(i) 拉插f(x)
ll c=1,p,s=0;
for(int i=0;i<=n;i++) c=c*(x-i)%mod;
for(int i=0;i<=n;i++){
p=c*inv[x-i]%mod*facinv[n-i]%mod*facinv[i]%mod;
if((n-i)&1) s=(s-p*f[i]%mod)%mod;
else s=(s+p*f[i]%mod)%mod;
}
return (s%mod+mod)%mod;
}
}L;
连续插值板子
对于一个 n n n次多项式。
连续插值 x ∈ [ 0 , n ] x\\in [0,n] x∈[0,n]
f k = ∑ i = 0 n f i ∏ j ≠ i k − j i − j \\large f_k=\\sum\\limits_{i=0}^n f_i \\prod\\limits_{j\\neq i}\\dfrac{k-j}{i-j} fk=i=0∑nfij=i∏i−jk−j
先提出来没有 k k k的 ∏ j ≠ i 1 i − j \\large \\prod\\limits_{j\\ne i}\\dfrac{1}{i-j} j=i∏i−j1
拆开: ∏ j ≠ i ( − 1 ) n − i i ! ( n − i ) ! \\large \\prod\\limits_{j\\ne i}\\dfrac{(-1)^{n-i}}{i! (n-i)!} j=i∏i!(n−i)!(−1)n−i
分子先预处理出所有的 c = ∏ i = 0 n ( k − i ) \\large c=\\prod\\limits_{i=0}^{n}(k-i) c=i=0∏n(k−i)
则 f k = ∑ i = 0 n f i ∏ j ≠ i k − j i − j = ∑ i = 0 n f i c i ! ( n − i ) ! ( − 1 ) n − i ( k − i ) \\large f_k=\\sum\\limits_{i=0}^n f_i \\prod\\limits_{j\\neq i}\\dfrac{k-j}{i-j}=\\sum\\limits_{i=0}^n f_i \\dfrac{c}{i!(n-i)!(-1)^{n-i}(k-i)} fk=i=0∑nfij=i∏i−jk−j=i=0∑nfii!(n−i)!(−1)n−i(k−i)c
预处理出阶乘逆元 f a c i n v ( i ) facinv(i) facinv(i) 和数的逆元 i n v ( i ) inv(i) inv(i)。
注意 i n v ( k − i ) inv(k-i) inv(k−i) 若 k k k很大是预处理不了的,只能费马小定理或者 e x g c d exgcd exgcd。
时间复杂度: O ( n ) O(n) O(n)
il ll inpo(ll *f,int n,ll x){ //给定 连续i属于[0,n] f(i) 拉插f(x)
ll c=1,p,s=0;
for(int i=0;i<=n;i++) c=c*(x-i)%mod;
for(int i=0;i<=n;i++){
p=c*inv[x-i]%mod*facinv[n-i]%mod*facinv[i]%mod;
if((n-i)&1) s=(s-p*f[i]%mod)%mod;
else s=(s+p*f[i]%mod)%mod;
}
return (s%mod+mod)%mod;
}
使用费马小定理求inv(x-i)
il ll inpo(ll *f,int n,ll x){ //给定 连续i属于[0,n] f(i) 拉插f(x)
ll c=1,p,s=0;
for(int i=0;i<=n;i++) c=c*(x-i)%mod;
for(int i=0;i<=n;i++){
p=c*Inv(x-i)%mod*facinv[n-i]%mod*facinv[i]%mod;
if((n-i)&1) s=(s-p*f[i]%mod)%mod;
else s=(s+p*f[i]%mod)%mod;
}
return (s%mod+mod)%mod;
}
习题
2019 ICPC 邀请赛(南昌) B-Polynomial
https://nanti.jisuanke.com/t/40254
考虑如何快速求出
S
(
n
)
=
∑
i
=
0
n
f
(
i
)
S(n)=\\sum\\limits_{i=0}^n f(i)
S(n)=i=0∑nf(i) 以上是关于拉格朗日插值法的主要内容,如果未能解决你的问题,请参考以下文章