拉格朗日插值学习笔记

目录

  • 拉格朗日插值学习笔记
    • 裸插值
    • 连续插值
    • 插值2
      • 实现

拉格朗日插值学习笔记

只是用来存放板子。。。

裸插值

不知道怎么证:

正在问老师,等回复

最新回复:该是啥值就是啥值吧

\[ f(k)=\sum_{i=0}^{n} y_{i} \prod_{i \neq j} \frac{k-x[j]}{x[i]-x[j]} \]


#include
#include
#include
#include
using namespace std;
#define ll long long
ll read(){
    ll x=0;int pos=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return pos?x:-x; 
}
const int N = 2001; 
const ll mod = 998244353;
ll n,k;
ll x[N],y[N];
ll ksm(ll a,ll b){

    ll res=1;
    while(b){

        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;

    }
    return res;
}
ll ginv(ll a){
    return ksm(a,mod-2);
}
ll lag(){
    ll res=0;
    for(int i=1;i<=n;i++){
        ll t1=1,t2=1;
        for(int j=1;j<=n;j++){

            if(i==j) continue;
            t1=t1*(k-x[j])%mod;

            t2=t2*(x[i]-x[j])%mod; 
        }
        res=(res+y[i]*t1%mod*ginv(t2)%mod+mod)%mod;
    }
    return res;
}
int main(){
    n=read(),k=read();
    for(int i=1;i<=n;i++){
        x[i]=read();y[i]=read();
    }
    printf("%lld",lag());
    return 0;
}

连续插值

那么此时式子变为:
\[ f(k)=\sum_{i=0}^{n} y_{i} \prod_{i \neq j} \frac{k-j}{i-j} \]
处理出
\[ pre_i=\prod _{j=0} ^i k-j \]

\[ suf_i=\prod _{j=i}^n k-j \]

分子:
\[ pre_{i-1}*suf_{i+1} \]
分母:
\[ fac[i]*fac[N-i]*(-1)^{N-i} \]
于是就可以\(nlogn\)了(逆元)

插值2

权当练习NTT了。。。

看到上面阶乘里面的i和n-i,是不是产生了什么想法?

具体地说,这就是一个卷积的形式

那么我们就可以用多项式乘法求出连续的一堆多项式的值了,时间复杂度从O(n)

实现

从题解里蒯出来的

式子是这样的:
\[ \sum_{i=0}^{n} f(i) \frac{(m+x) ! /(m+x-n-1) !}{(m+x-i)(-1)^{n-i} !(n-i) !} \]

然后卷出来往右平移n就行了(

你可能感兴趣的:(拉格朗日插值学习笔记)