[多項式學習筆記1]拉格朗日插值定理


[多項式學習筆記1]拉格朗日插值定理

算法簡介

拉格朗日插值法是以法國18世紀數學家約瑟夫·拉格朗日命名的一種多項式插值方法。

適用問題

拉格朗日插值定理主要是用來解決下面這樣的問題:

給出 n 個點 (xi,yi)(保證 xi 互不相同),要求找出一個過所有點的多項式函數 f(x)。 

顯然最直觀的方法是采用高斯消元,但高斯消元時間復雜度較高且有精度誤差

這時候就可以考慮用拉格朗日插值定理了

算法流程

顯然對於每個點,我們嘗試找出一個函數 fi(x),使得 fi(xi) = yi, 並且對於其他的所有橫坐標 xj(j!=i) 有 fi(xj) = 0。那么把 n 個 fi(x) 加起來就能得到要求的函數 f(x) 了

可以推出式子:

 

 

 

 時間復雜度 O(n^2)

代碼(luogu模板)

#include<bits/stdc++.h>

#define ll long long

using namespace std;

inline ll read()
{
    ll f = 1 , x = 0;
    char ch;
    do
    {
        ch = getchar();
        if(ch=='-') f=-1;
    } while(ch<'0'||ch>'9');
    do
    {
        x=(x<<3) + (x<<1) + ch - '0';
        ch = getchar();
    }while(ch>='0'&&ch<='9');
    return f*x;
}

const int MAXN = 2000 + 10;
const ll MOD = 998244353;

inline ll Pow(ll a,ll b)

{
    ll ans = 1,mul = a;
    while(b)

    {
        if(b&1) ans = (ans * mul) % MOD;
        mul = (mul * mul)%MOD;

        b>>=1;

    }
    return ans;
}

inline ll inv(ll a)
{
    return Pow(a,MOD-2);
}

ll n,k;
ll x[MAXN],y[MAXN];
ll ans;

int main()
{
    n = read(),k = read();
    for(int i=1;i<=n;i++) x[i] = read(),y[i] = read();
    for(int i=1;i<=n;i++)
    {
        ll res1 = y[i] % MOD;
        ll res2 = 1;
        for(int j=1;j<=n;j++)

        {
            if(i == j) continue;
            res1 = (res1 * (k - x[j]%MOD + MOD)%MOD)%MOD;
            res2 = (res2 * ((x[i] - x[j]%MOD + MOD)%MOD))%MOD;
        }
        ans = (ans + (res1 * inv(res2) % MOD)%MOD) % MOD;
    }
    cout << ans << endl;
}

拉格朗日插值定理的擴展

  • 當X取值連續時,可以通過記錄前綴和和后綴和做到線性時間復雜度
  • 重心拉格朗日插值定理:
拉格朗日插值法的公式結構整齊緊湊,在理論分析中十分方便,然而在計算中,當插值點增加或減少一個時,所對應的基本多項式就需要全部重新計算,
於是整個公式都會變化,非常繁瑣
。這時可以用重心拉格朗日插值法

  將拉格朗日插值定理變形為:

  

  其中 g =

         

  然后另 Ti =

         

  當增加一個點時直接增加ti即可

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM