拉格朗日插值

BZOJ2655

可以发现答案在n确定时为关于A的2*n次多项式

  
dp求出小范围答案后插值即可
#include <cstdio>
#define LL long long 
  
  LL mo,fac[2001],y[2001],x[2001],A,dp[2001][2001];
  int n;
  
  LL qpow(LL bas,int powe){
      LL ret=1;
      for (;powe;bas*=bas,bas%=mo){
        if (powe&1) ret*=bas,ret%=mo;
      powe=powe>>1;    
    }
    return(ret);
  }

  LL work(){
      LL ret=0;
      for (int i=0;i<=2*n;i++){
        LL up=y[i],down=1;
        for (int j=0;j<=2*n;j++)
          if (i!=j){
            up*=(A-x[j]);up%=mo;
          down*=(x[i]-x[j]);down%=mo;    
        }
      down+=mo;down%=mo;
      ret+=up*qpow(down,mo-2)%mo;ret%=mo;
    }
    return(ret);
  }

  int main(){      
      scanf("%lld%d%lld",&A,&n,&mo);
      fac[0]=1;
      for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mo;
      dp[0][0]=1;
      int j;
      for (int i=1;i<=2*n+1;i++)
        for (dp[i][0]=1,j=1;j<=n;j++)
          dp[i][j]=(dp[i-1][j]+dp[i-1][j-1]*i%mo)%mo;
    if (A<=2*n+1) {printf("%lld\n",dp[A][n]*fac[n]%mo);return(0);}
    for (int i=1;i<=2*n+1;i++) x[i-1]=i,y[i-1]=dp[i][n];
    printf("%lld\n",work()*fac[n]%mo);
  } 

 

posted @ 2017-02-19 18:52  z1j1n1  阅读(181)  评论(0编辑  收藏  举报