拉格朗日插值
拉格朗日插值
拉格朗日插值主要解决求高次多项式的问题,和求特定的条件限制的多项式。
本文前置知识:多项式除法,线性同余方程,中国剩余定理,乘法逆元(逆元前置:扩展欧几里得(线性同余方程)或者快速幂(由费马小定理所得)或者线性求逆元)。
主要懂得加粗知识就大概差不多了,感觉好啰嗦,主要想记录一下,懂得这些前置知识学会拉格朗日插值是很轻松的
拉格朗日插值求多项式
有\(n\)个点\((x_i,y_i)\),求出过这\(n\)个点的多项式\(f(x)\)。
则\(n\)个\(y_i\)对应着\(n\)个\(x_i\),对于每个\(f(y_i)\),有:
\(f(x)\equiv y_i(mod (x-x_i))\)
因为\(f(x)-f(x_i)=(a_0-a_0)+a_1(x^1-x_i^1)+...+a_n(x^n-a^n)\)其中\(a\)位多项式中的系数和常数,所以我们可以得到:
$ \begin{cases} f(x)\equiv y_1\pmod{(x-x_1)}\ f(x)\equiv y_2\pmod{(x-x_2)}\ \cdots\ f(x)\equiv y_n\pmod{(x-x_n)} \end{cases} $
这是一个一元线性同余方程接下来我们根据中国剩余定理,\(x=\sum_{i=1}^k a_ic_i \pmod n\)
可得:$M= M=\prod_{i=1}^n{(x-x_i)},m_i=\dfrac M{x-x_i}=\prod_{j\ne i}{(x-x_j)} $
求\(m_i\)的逆元,然后可得$f(x)=\sum_{i=1}^n{y_i\prod_{j\ne i}{\dfrac {x-x_j}{x_i-x_j}}} $
这个过程中如果求逆元是用的快速幂\((logn)\)的话时间复杂度为\(O(n^2log n)\).
例题:
这里给出模板那道题的代码,注意只需要求\(f(k)\)即可不用全部求出。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int MN=2e3+100;
int n,k,ans,x[MN],y[MN];
inline int qpow(int a,int b){
int res=1ll;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
inline int inv(int x){return qpow(x,mod-2);}
signed main(){
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;++i)scanf("%lld%lld",&x[i],&y[i]);
for(int i=1;i<=n;++i){
int son=y[i]%mod;
int mom=1ll;
for(int j=1;j<=n;++j){
if(i!=j)son=son*(k-x[j])%mod,mom=mom*(x[i]-x[j])%mod;
}
ans=(ans+son*inv(mom))%mod;
}
printf("%lld\n",(ans%mod+mod)%mod);
return 0;
}