拉格朗日插值总结

问题

给定 \(n\) 个点,确定一个多项式 \(f(x)=\sum_{i=0}^{n-1}a_ix^i\)。求 \(f(k)\)

解法

拉格朗日插值的核心思想是通过构造 \(n\) 个函数,满足第 \(i\) 个函数经过 \((x_1,0),(x_2,0),\cdots,(x_i,y_i),\cdots,(x_n,0)\),将这 \(n\) 个函数的系数累加即可得到原函数。

具体地,有\(f_i(x)= y_i \prod_{i \not = j} \frac{x-x_j}{x_i-x_j}\)

故原函数

\[\begin{aligned} f(x)=\sum_{i=1}^{n}y_i \prod_{i \not = j} \frac{x-x_j}{x_i-x_j} \end{aligned} \]

那么将原问题的 \(k\) 代入得:

\[\begin{aligned} f(k)=\sum_{i=1}^{n}y_i \prod_{i \not = j} \frac{k-x_j}{x_i-x_j} \end{aligned} \]

这样就在 \(\Theta(n^2)\) 的时间求得一个多项式的值。

练习

P4781 【模板】拉格朗日插值

#include <bits/stdc++.h>
#define int long long

using namespace std;

inline int read()
{
    int w=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+(ch^48);
        ch=getchar();
    }
    return w*f;
}
void write(int x)
{
    if(x<0) x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

const int mod=998244353;
const int maxn=2e3+10;
int n,k;
int x[maxn],y[maxn];
int qpow(int a,int b,int mod)
{
    int res=1;
    while(b)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}

signed main()
{
    n=read(),k=read();
    for(int i=1;i<=n;++i)
    {
        x[i]=read(),y[i]=read();
    }
    int ans=0;
    for(int i=1;i<=n;++i)
    {
        int fz=1,fm=1;
        for(int j=1;j<=n;++j)
        {
            if(j!=i)
            {
                (fz*=(k-x[j]+mod)%mod)%=mod;
                (fm*=(x[i]-x[j]+mod)%mod)%=mod;
            }
        }
        (ans+=fz*qpow(fm,mod-2,mod)%mod*y[i])%=mod;
    }
    cout<<ans<<endl;
    return 0;
}
posted @ 2025-01-16 19:16  vanueber  阅读(45)  评论(0)    收藏  举报