【計蒜客】2019 南昌邀請賽 B題

題解:拉格朗日插值裸題

/*
2019 ICPC南昌區域賽 B題 
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
//mod一定要是質數
const int mod=9999991;
 
int pv[2000]; //前幾項, 前面無效值用0佔位
int st=1,ed;           //使用上面數組下標爲[st,ed]的數據
 
ll fac[2000],inv[2000],facinv[2000];
ll pre[2000],saf[2000];
 
//預處理: 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()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,q;
		memset(pv,0,sizeof(pv));
		cin>>n>>q;
		ed=n+1;
		for(int i=1;i<=n+1;i++)
		{
			cin>>pv[i];
		}
		init();
		pv[n+2]=cal(n+2);
		for(int i=1;i<=n+2;i++)
		{
			pv[i]=(pv[i]+pv[i-1])%mod;
		}
		ed=n+2;
		init();
		while(q--)
		{
			int l,r;
			cin>>l>>r;
			ll ans=(cal(r+1)-cal(l)+mod)%mod;
			cout<<ans<<endl;
		}
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章