拉格朗日插值模板

版权声明:本文为博主瞎写的,请随便转载 https://blog.csdn.net/sdut_jk17_zhangming/article/details/90756329
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long ll;
const int N = 1100;
//mod一定要是质数
const int mod=9999991;

int pv[N]; //前几项, 前面无效值用0占位
int st=1,ed=1100;           //使用上面数组下标为[st,ed]的数据

ll fac[N+5],inv[N+5],facinv[N+5];
ll pre[N+5],saf[N+5];

//预处理: fac[]阶乘, inv[]逆元, facinv[]阶乘逆元
//只需要main函数内调用一次!
void init()
{
    fac[0]=inv[0]=facinv[0]=1;
    fac[1]=inv[1]=facinv[1]=1;
    for(int i=2;i<ed+3;++i)
    {
        fac[i]=fac[i-1]*i%mod;
        inv[i]=mod-(mod/i*inv[mod%i]%mod);
        facinv[i]=facinv[i-1]*inv[i]%mod;
    }
}

//计算第x0项的值
//复杂度O(ed-st)
ll cal(ll x0)
{
    int n=ed-st;
    x0=((x0%mod)+mod)%mod;
    pre[0]=((x0-st)%mod+mod)%mod;
    saf[n]=((x0-st-n)%mod+mod)%mod;
    for(int i=1;i<=n;++i)
    {
        pre[i]=((pre[i-1]*(x0-st-i))%mod+mod)%mod;
        saf[n-i]=((saf[n-i+1]*(x0-st-n+i))%mod+mod)%mod;
    }
    ll res=0;
    for(int i=0;i<=n;++i)
    {
        ll fz=1;
        if(i!=0)fz=fz*pre[i-1]%mod;
        if(i!=n)fz=fz*saf[i+1]%mod;
        ll fm=facinv[i]*facinv[n-i]%mod;
        if((n-i)&1)fm=mod-fm;
        (res+=pv[i+st]*(fz*fm%mod)%mod)%=mod;
    }
    return res;
}

int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    init();
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        st = 1;
        ed = n+1;
        for(int i = 1;i <= n+1;i++) cin>>pv[i];
        for(int i = n+1;i <= n+5;i++) pv[i] = cal(i);
        for(int i = 1;i <= n+5;i++) pv[i] += pv[i-1];
        st = 1;
        ed = n + 5;
        while(m--)
        {
            int l,r;
            cin>>l>>r;
            l++,r++;
            ll ans = (cal(r)-cal(l-1) + mod)%mod;
            cout<<ans<<endl;
        }
    }
}

 

展开阅读全文

没有更多推荐了,返回首页