# 拉格朗日插值法及应用

7 篇文章 0 订阅

## 拉格朗日插值法

• 快速根据点值逼近函数
• 在取点大于 n n $n$的情况下解出$n$$n$次多项式是唯一解。

i=1ni=n(n+1)2 ∑ i = 1 n i = n ( n + 1 ) 2 $\sum\limits_{i=1}^ni=\frac{n(n+1)}{2}$

### 一般方法

${f}_{i}\left(x\right)=\frac{\prod _{j\ne i}\left(x-{x}_{j}\right)}{\prod _{j\ne i}\left({x}_{i}-{x}_{j}\right)}\ast {y}_{i}$

g(x)=i=0nfi(x) g ( x ) = ∑ i = 0 n f i ( x )

### 重心拉格朗日插值法

fi(x)=ji(xxj)ji(xixj)yi f i ( x ) = ∏ j ≠ i ( x − x j ) ∏ j ≠ i ( x i − x j ) ∗ y i

g(x)=i=0nfi(x) g ( x ) = ∑ i = 0 n f i ( x )

l(x)=i=1n(xxi) l ( x ) = ∏ i = 1 n ( x − x i )

ωi=yiji(xixj) ω i = y i ∏ j ≠ i ( x i − x j )

g(x)=l(x)i=1nωi(xxi) g ( x ) = l ( x ) ∑ i = 1 n ω i ( x − x i )

## 应用

### bzoj4559:成绩比较

xi=1UxiRxUxinRx1(Ux109,Rx102,n102) ∏ x ∑ i = 1 U x i R x （ U x − i ） n − R x − 1 ( U x ≤ 10 9 , R x ≤ 10 2 , n ≤ 10 2 )

### bzoj3453:XLkxc

f(n)=i=0nj=1a+ibx=1jxk(k123,n,a,b109) f ( n ) = ∑ i = 0 n ∑ j = 1 a + i b ∑ x = 1 j x k ( k ≤ 123 , n , a , b ≤ 10 9 )

x=1jxk ∑ x = 1 j x k

g(m)=j=1mx=1jxk g ( m ) = ∑ j = 1 m ∑ x = 1 j x k

$f\left(n\right)=\sum _{i=0}^{n}g\left(a+ib\right)$

1.每个求和号一般会增加多项式次数1.
2.插值可以嵌套。

Code for bzoj3453:

#include<bits/stdc++.h>
using namespace std;
struct IO
{
streambuf *ib,*ob;
int buf[50];
inline void init()
{
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
ib=cin.rdbuf();ob=cout.rdbuf();
}
{
char ch=ib->sbumpc();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
return i*f;
}
inline void W(int x)
{
if(!x){ob->sputc('0');return;}
if(x<0){ob->sputc('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0])ob->sputc(buf[buf[0]--]+'0');
}
}io;
const int mod=1234567891,lim=130;
int k,a,n,d;
int fg[150],fy[150],wf[150],fac[150],inv[150];
inline int power(int a,int b)
{
int res=1;
for(;b;b>>=1)
{
if(b&1)res=1ll*res*a%mod;
a=1ll*a*a%mod;
}
return res;
}
int DIV;
inline int calc(int *w,int u)
{
if(u<=lim)return w[u];
static int l,res,Div;
l=1,res=0,Div=DIV;
for(int i=1;i<=lim;i++)l=1ll*l*((1ll*u-i+mod)%mod)%mod;
for(int i=1;i<=lim;i++)
{
res=(1ll*res+1ll*Div*power(((1ll*u-i+mod)%mod),mod-2)%mod*w[i]%mod)%mod;
Div=1ll*Div*(i-lim+mod)%mod*inv[i]%mod;
}
return 1ll*res*l%mod;
}
int main()
{
fac[0]=fac[1]=inv[0]=inv[1]=1;DIV=1;
for(int i=2;i<=lim;i++)inv[i]=(-1ll*(mod/i)*inv[mod%i]%mod+mod)%mod;
for(int i=1;i<=lim;i++)fac[i]=1ll*fac[i-1]*i%mod;
for(int i=2;i<=lim;i++)DIV=1ll*DIV*power(1-i+mod,mod-2)%mod;
while(T--)
{
for(int i=1;i<=lim;i++){fg[i]=power(i,k);}
for(int i=1;i<=lim;i++){fg[i]=(1ll*fg[i]+fg[i-1])%mod;}
for(int i=1;i<=lim;i++){fg[i]=(1ll*fg[i]+fg[i-1])%mod;}
fy[0]=calc(fg,a);
for(int i=1;i<=lim;i++)
{
fy[i]=(1ll*fy[i-1]+calc(fg,(1ll*a+1ll*i*d)%mod))%mod;
}
printf("%d\n",calc(fy,n));
}
}
• 15
点赞
• 44
收藏
觉得还不错? 一键收藏
• 4
评论
07-03 3139
01-30
04-16 1166
01-08 3万+
06-03 3182
07-14
12-26
07-14
12-13
08-04 784
02-17 1190
09-01 5506

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。