数值算法

拉插

普通拉插

这篇博客的主要内容。

插值是一种通过已知的、离散的数据点推算一定范围内的新数据点的方法。插值法常用于函数拟合中。

在信息学竞赛中常用于,题目中直接或间接的给出了 \(n+1\) 个点,让我们求由这些点构成的多项式在某一位置的取值。

我们可以考虑对每一个点 构造一个函数 \(f_i(x)\) 使其在 \(x_i\) 处值为 \(y_i\) 在其他 \(x_j\) 处为 \(0\) 。那么我们要的多项式就这些函数加起来。

我们设 $f_i(x)=a\cdot \prod_{j\ne i}(x-x_j) $ 我们用已知的一个点 \((x_i,y_i)\) 代入可以得到 \(a={y_i\over\prod_{j\ne i}(x_i-x_j)}\) 。(其它点在后面一坨已经变成 \(0\) ,求不出 \(a\) 值) 。

所以最后的答案是 \(\sum y_i\prod_{j\ne i}{(x-x_j)\over (x_i-x_j)}\)

对于这个式子我们可以暴力 \(O(n^2)\) 来计算。还可以用多项式优化到 \(O(n\log^2 n)\)

#include  <bits/stdc++.h>
using namespace std;
const int mod=998244353,N=2e3+10;
int n;
long long ans=0,k,x[N],y[N];
long long ksm(long long a,int b)
{
    long long res=1;
    while(b)
    {
        if(b&1)res=res*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return res;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>x[i]>>y[i];
    for(int i=1;i<=n;i++)
    {
        long long ans1=1,ans2=1;
        for(int j=1;j<=n;j++)
        {
            if(j==i)continue;
            ans1=ans1*((k-x[j]+mod)%mod)%mod;
            ans2=ans2*((x[i]-x[j]+mod)%mod)%mod;
        }
        ans=(ans+y[i]*ans1%mod*ksm(ans2,mod-2)%mod)%mod; //ans=
    }
    cout<<ans<<'\n';
    return 0;
}

\(O(n)\) 拉插

重心拉插

牛顿插值(会咕)

高斯消元

已经写过了。这里

posted @ 2025-05-07 18:11  exCat  阅读(31)  评论(0)    收藏  举报