南昌ICPC拉格朗日求值法題目

Polynomial
題意:給出一個n次多項式F(x),給出F(0),F(1)…F(n),m個詢問給出l,r,求F[l]+F[l+1]+…+F[r-1]+F[r]。
n<=1000,m<=2000,1<=l<=r<=9999990。
思路:暴力肯定不行,需要求一共1e7的F[]數組,只要不是o(1)的求法就一定會爆,所有轉化思路,猜測一個n次式的前綴和是n+1次式,爲了證明這個假設,我弄了個3次的式子然後求出他的前綴和的四次式,符合猜想,所以假設猜測成立,然後就拉格朗日求出F[n+1],然後用sum[i]求出F[i]的前綴和,然後用拉格朗日求值法可以利用拉格朗日求值法的第二種方法o(n)的得到sum[i],然後對每個詢問sum[r]-sum[l-1]即可,因爲某個地方忘%了WA成shi了。數論的題實現真噁心。

#include<iostream>
#include<cstdio>
using namespace std;
const int MAX_N=1010;
const long long MOD=9999991;
long long f[MAX_N];
long long sum[MAX_N];
long long F[MAX_N];
long long pre[MAX_N],suf[MAX_N],Inv[10000100];
long long C(long long x){
 if(x%2==0)
 return 1;
 else
 return -1;
}
long long ask(long long k,long long n){
 if(k<=n)
 return sum[k];
 long long i;
 pre[0]=k;
 for(i=1;i<=n;i++){
  pre[i]=pre[i-1]*(k-i)%MOD;
 }
 suf[n]=k-n;
 for(i=n-1;i>=0;i--){
  suf[i]=suf[i+1]*(k-i)%MOD;
 }
 long long ans=0;
 ans=(ans+sum[0]*suf[1]%MOD*Inv[(F[n]*C(n)+MOD)%MOD]%MOD)%MOD;
 ans=(ans+sum[n]*pre[n-1]%MOD*Inv[F[n]]%MOD)%MOD;
 for(i=1;i<n;i++){
  ans=(ans+sum[i]*pre[i-1]%MOD*suf[i+1]%MOD*Inv[(F[i]*C(n-i)+MOD)%MOD*F[n-i]%MOD]%MOD)%MOD;
 }
 return ans;
}
int main(void){
 int T;
 long long n,m;
 long long i,j;
 cin>>T;
 F[0]=1;
 for(i=1;i<=1005;i++)
 F[i]=F[i-1]*i%MOD;
 long long p=MOD;
 Inv[1]=1;
 for(i=2;i<p;i++)
 Inv[i]=(p-p/i)*Inv[p%i]%p;
 while(T--){
  scanf("%lld%lld",&n,&m);
  for(i=0;i<=n;i++)
  scanf("%lld",&f[i]);
  f[n+1]=0; 
  for(i=0;i<=n;i++){
   long long res=1;
   long long fact=1;
   for(j=0;j<=n;j++){
    if(i==j)
    continue;
    res=res*(n+1-j)%MOD;
    fact=fact*((i-j+MOD)%MOD)%MOD;
   }
   res=res*Inv[fact]%MOD;
   f[n+1]=(f[n+1]+f[i]*res%MOD)%MOD;
  }
  sum[0]=f[0];
  for(i=1;i<=n+1;i++){
   sum[i]=(sum[i-1]+f[i])%MOD;
  }
  long long l,r;
  for(i=0;i<m;i++){
   scanf("%lld%lld",&l,&r);
   printf("%lld\n",(ask(r,n+1)-ask(l-1,n+1)+MOD)%MOD);
  }
 }
 return 0;
}
發佈了62 篇原創文章 · 獲贊 6 · 訪問量 1939
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章