zoukankan      html  css  js  c++  java
  • 拉格朗日插值

    定义

    一般地,若已知 (y=f(x)), 在互不相同 (n+1) 个点:(x_0,x_1,dots x_n) 处的函数值:(y_0,y_1,dots y_n) ,即该函数过点:((x_0,y_0),(x_1,y_1),dots (x_n,y_n)) ,则可以考虑构造一个过这 (n+1) 个点的,最高次幂不超过 (n) 的多项式:

    [y=P_n(x) ]

    使其满足:

    [P_n(x_k)=y_k,k=0,1,dots ,n ]

    定理

    满足插值条件的,次数不超过 (n) 的多项式是存在而且是唯一的。

    分析

    可以理解为,将该多项式 (P_n(x)) 拆成 (n+1) 个函数的和的形式:

    [P_n(x)=sum_{i=0}^{n}{f_i(x)} ]

    其中,第 (i) 个函数 (f_i(x)) 满足除 (f_i(x_i)=y_i) 外,其它位置取值都为 (0)。即:

    [f_i(x)=a_i prod_{i eq j}{(x-x_j)} ]

    代入 (f(x_i)=y_i),可以得出:

    [a_i=frac{y_i}{prod_{i eq j}{(x_i-x_j)}} ]

    即插值公式为:

    [egin{align} P_n(x) &=sum_{i=0}^{n}{frac{y_i·prod_{i eq j}{(x-x_j)}}{prod_{i eq j}{(x_i-x_j)}}}\ end{align} ]

    另外,还有拉格朗日插值的优化:重心拉格朗日。
    https://www.cnblogs.com/ECJTUACM-873284962/p/6833391.html

    Polynomial-2019南昌邀请赛

    题意

    定义(f(x)=a_0+a_1 imes x^1+a_2 imes x^2+dots +a_n imes x^n),现在已知 (f_{(0)},f_{(1)},f_{(2)},dots ,f_{(n)}),现在要求:

    [sum_{i=L}^{R}f_{(i)} mod 9999991 ]

    题目链接:https://nanti.jisuanke.com/t/40254

    分析

    根据拉格朗日插值的公式,可以得出 (f(x)) 的通项:

    [f(x)=sum_{i=0}^{n}{frac{y_i}{prod_{i eq j}{(i-j)}}·prod_{i eq j}{(x-j)}} ]

    其中常数项部分,可以通过通过阶乘和逆元预处理出来,注意 (-1)。而后面与 (x) 有关的项,可以代入 (x) 通过前缀积和后缀积求出。

    但是如果要求一段区间内的函数值之和,可以考虑求出前缀和。因为 (n) 次多项式的前缀和是 (n+1) 次多项式,且前缀和需要 (n+1) 个点来求出。因此,可以利用 (f(x)) 求出 (f(n+1)) ,从而求出前缀和的多项式在各点的取值,进而求出前缀和的多项式,求差即可。

    代码

    #include<bits/stdc++.h>
    //先求Pn的多项式,然后求其前缀和的多项式
    using namespace std;
    typedef long long ll;
    const int mod=9999991;
    const int N=1e3+10;
    const int M=1e7+5;
    ll fact[N],sum[M],inv[N],pre[N],suf[N],f[N];
    ll power(ll x,ll y)
    {
        ll res=1;
        x%=mod;
        while(y)
        {
            if(y&1) res=res*x%mod;
            x=x*x%mod;
            y>>=1;
        }
        return res;
    }
    void init()
    {
        int maxn=1000;
        fact[0]=1;
        for(int i=1;i<=maxn;i++)
            fact[i]=1LL*fact[i-1]*i%mod;
        inv[maxn]=power(fact[maxn],mod-2);
        for(int i=maxn-1;i>=0;i--)
            inv[i]=1LL*inv[i+1]*(i+1)%mod;
    }
    ll solve(ll h[],int x,int n)//求出对应的函数值
    {
        if(x<=n) return h[x];
        ll res=0;
        pre[0]=x,suf[n]=(x-n);
        for(int j=1;j<=n;j++)
            pre[j]=1LL*pre[j-1]*(x-j)%mod;
        for(int j=n-1;j>=0;j--)
            suf[j]=1LL*suf[j+1]*(x-j)%mod;
        for(int i=0;i<=n;i++)
        {
            ll tmp=h[i];
            tmp=tmp*inv[n-i]%mod*inv[i]%mod;
            int flag=((n-i)%2?-1:1);
            tmp=tmp*flag%mod;
            if(i>0) tmp=tmp*pre[i-1]%mod;
            if(i<n) tmp=tmp*suf[i+1]%mod;
            res=(res+tmp+mod)%mod;
        }
        return res;
    }
    int main()
    {
        int T,L,R,n,m;
        scanf("%d",&T);
        init();
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=0;i<=n;i++)
                scanf("%lld",&f[i]);
            f[n+1]=solve(f,n+1,n);
            sum[0]=f[0];
            for(int i=1;i<=n+1;i++)
                sum[i]=(sum[i-1]+f[i])%mod;
            while(m--)
            {
                scanf("%d%d",&L,&R);
                printf("%lld
    ",(solve(sum,R,n+1)-solve(sum,L-1,n+1)+mod)%mod);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    JMM简述
    spring简读
    Linux常用命令
    基于java的八大排序实现
    数据库事务说明
    BIO、NIO、AIO区别与联系
    ThreadLocal 是什么?有哪些使用场景?
    ConcurrentHashMap 和 Hashtable 比较,为什么推荐使用ConcurrentHashMap?
    sychronized设计原理
    MySQL索引详解
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13591380.html
Copyright © 2011-2022 走看看