【模板】拉格朗日插值

本文介绍了拉格朗日插值法的一般形式和唯一性,说明了其在多项式单点求值中的应用,并提供了一个典例,展示了如何利用拉格朗日插值法优化求解复杂度。此外,还给出了相关代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般形式

对于 n n 阶多项式f(x),给定二维平面上互不相同的 n+1 n + 1 个点 (xi,f(xi))(0in) ( x i , f ( x i ) ) ( 0 ≤ i ≤ n ) ,那么由拉格朗日插值法可得:
f(x)=ni=0f(xi)nj=0,jixxjxixj f ( x ) = ∑ i = 0 n f ( x i ) ∏ j = 0 , j ≠ i n x − x j x i − x j
可以观察到 f(x) f ( x ) (x0,x1,..,xn) ( x 0 , x 1 , . . , x n ) 上都是成立的。


唯一性

可以证明,对于 n n 阶多项式f(x),存在二维平面上互不相同的 n+1 n + 1 个点使得该多项式通过拉格朗日插值法表示后具有唯一性。
由拉格朗日插值的一般形式计算得到一个 n n 阶多项式。将每项的系数带入,可以得到一个范德蒙德矩阵,而n阶范德蒙德矩阵的行列式一定不为0,所以存在逆矩阵。
矩阵的逆矩阵具有唯一性,反之存在逆矩阵的矩阵也具有唯一性。所以 f(x) f ( x ) 具有唯一性。


应用

可以在 O(n2) O ( n 2 ) 的时间内通过给定的 n+1 n + 1 个点求出 n n 阶多项式f(x)在某一点 k k 上的取值f(k)
同样,若该式具有一定特殊性,如给定的点是 x x 轴上连续的一端,那么可以在O(n)时间内求解。
但注意拉格朗日插值法求多项式对手算很不友好。且多用于多项式单点求值,而非求解多项式。


典例

给定 n,k n , k (n107,k105) ( n ≤ 10 7 , k ≤ 10 5 )
求: ni=1ik ∑ i = 1 n i k
这题的复杂度通过巧妙的拉格朗日插值的运用可以从 O(nlogk) O ( n log ⁡ k ) 降到 O(k) O ( k )
考虑到可以将这种形式的式子转化为 k k 阶多项式f(x)。而求的是 f(n) f ( n ) 的答案。
那么直接暴力求出前 k k 项带入拉格朗日插值一般形式算出即可。
因为xi是连续的,所以求解时的连乘就变成了阶乘,化简整理后可得:
f(x)=ki=1(xi)kj=1f(j)1(j1)!(1)kj(kj)!(xj) f ( x ) = ∏ i = 1 k ( x − i ) ∑ j = 1 k f ( j ) 1 ( j − 1 ) ! ( − 1 ) k − j ( k − j ) ! ( x − j )


代码

传送门:洛谷:【模板】拉格朗日插值

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int x[2002],y[2002],n,k,ans;

inline int ad(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
inline int dc(int x,int y){x-=y;if(x<0) x+=mod;return x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}

template<class T>
inline void rd(T &x)
{
    char c=getchar();int f=0;x=0;
    while(!isdigit(c)) {if(c=='-') f=1;c=getchar();}
    while(isdigit(c)) {x=x*10+(c^48);c=getchar();}
    if(f) x=-x;
}

inline int fp(int x,int y)
{
    int re=1;
    for(;y;y>>=1,x=mul(x,x)) 
     if(y&1) re=mul(re,x);
    return re; 
}

int main(){
    int i,j,res,rep;
    rd(n);rd(k);
    for(i=1;i<=n;++i) rd(x[i]),rd(y[i]);
    for(i=1;i<=n;++i){
        res=y[i];rep=1;
        for(j=1;j<=n && res!=0;++j) if(i!=j){
            res=mul(dc(k,x[j]),res);
            rep=mul(rep,dc(x[i],x[j])); 
        }
        ans=ad(ans,mul(res,fp(rep,mod-2)));
    }
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值