拉格朗日插值
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); }