数值算法
拉插
普通拉插
这篇博客的主要内容。
插值是一种通过已知的、离散的数据点推算一定范围内的新数据点的方法。插值法常用于函数拟合中。
在信息学竞赛中常用于,题目中直接或间接的给出了 \(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)\) 拉插
重心拉插
牛顿插值(会咕)
高斯消元
已经写过了。这里。

浙公网安备 33010602011771号