zoukankan      html  css  js  c++  java
  • 多项式入门——拉格朗日插值

    多项式入门——拉格朗日插值

    插值用来求解这样一类问题:给定 (n)((x_i,y_i)) 求过这些点的多项式。

    1 简介

    (f(x)) 为这个多项式,我们有:

    [f(x)equiv f(a)mod (x-a) ag{1} ]

    这是因为:

    [f(x)-f(a)=(a_0-a_0)+a_1(x-a)+a_2(x^2-a^2)+... ]

    而后者显然有一个根为 (a) ,所以 ((1)) 式得证。

    通过把这 (n) 个点代入我们可以得到:

    [egin{cases} f(x)equiv y_1mod x-x_1\ ...\ f(x)equiv y_nmod x-x_n end{cases} ]

    显然模数互质,所以我们考虑用中国剩余定理来解决这个事情。

    (M=prod_{i=1}^n(x-x_i))(m_i=frac{M}{x-x_i}=prod_{i ot= j}(x-x_j)) 。并且在模 (x-x_i) 的意义下,我们有:

    [m_i^{-1}=frac{1}{prodlimits_{i ot=j}(x_i-x_j)} ]

    这是因为我们有:

    [prod_{i ot =j}(x-x_j)equiv prod_{i ot =j}(x-x_j-x+x_i)=prod_{i ot =j}(x_i-x_j) ]

    所以上述结论成立。

    所以我们有:

    [f(x)equiv sumlimits_{i=1}^ny_im_im_i^{-1}equiv sumlimits_{i=1}^ny_iprodlimits_{j ot=i}frac{x-x_j}{x_i-x_j} ]

    这个东西可以在 (n^2) 的时间内求出。

    2 例题

    链接

    直接模拟上面的过程即可。

    #include<bits/stdc++.h>
    #define dd double
    #define ld long double
    #define ll long long
    #define uint unsigned int
    #define ull unsigned long long
    #define N 2010
    #define M number
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    const ll mod=998244353;
    
    template<typename T> inline void read(T &x) {
        x=0; int f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        x*=f;
    }
    
    inline ll ksm(ll a,ll b,ll mod){
        ll res=1;
        while(b){
            if(b&1) (res*=a)%=mod;
            a=a*a%mod;
            b>>=1;
        }
        return res;
    }
    
    inline ll inv(ll a){
        return ksm(a,mod-2,mod);
    }
    
    ll n,k,x[N],y[N],ans;
    
    int main(){
        read(n);read(k);
        for(int i=1;i<=n;i++){
            read(x[i]);read(y[i]);
        }
        for(int i=1;i<=n;i++){
            ll fenzi=1,fenmu=1;
            for(int j=1;j<=n;j++){
                if(j==i) continue;
                fenmu*=(x[i]-x[j]);fenmu%=mod;
                fenzi*=(k-x[j]);fenzi%=mod;
            }
            ans+=y[i]*fenzi%mod*inv(fenmu)%mod;ans%=mod;
        }
        printf("%lld
    ",(ans%mod+mod)%mod);
        return 0;
    }
    

    注意:

    1. 需要把分母乘出来再求逆元,这样复杂度的瓶颈就不会是求逆元。

    2. 结尾注意化为正数。

  • 相关阅读:
    在线考试————随机出题
    HTTP协议
    团队
    做作业
    图书馆管理说明书性能
    关于敏捷开发的学习
    运行环境
    图书馆管理系统说明书
    性能(2)
    作业
  • 原文地址:https://www.cnblogs.com/TianMeng-hyl/p/14987874.html
Copyright © 2011-2022 走看看