2019ICPC邀请赛南昌B Polynomial 拉格朗日插值
让你求f(L)到f(R)的和。
我们考虑前缀和,F(x)必定是比f(x)次数高1的多项式,所以我们先插值插出f(n+1)。然后求出n+1个前缀和,插值出前缀和即可。
1 #include <cstdio> 2 using namespace std; 3 typedef long long ll; 4 const int mo = 9999991; 5 int n,m,T; 6 ll y1[1100],y2[1100],pre[1100],suf[1100],inv[1100]; 7 ll fpow(ll x,int k) 8 { 9 if (k == 0) 10 return 1; 11 ll t = fpow(x,k >> 1); 12 if (k & 1) 13 return t * t % mo * x % mo; 14 return t * t % mo; 15 } 16 ll calc(ll y[],int n,int x) 17 { 18 if (x <= n) 19 return y[x]; 20 pre[0] = x; 21 suf[n] = x - n; 22 for (int i = 1;i <= n;i++) 23 pre[i] = pre[i - 1] * (x - i) % mo; 24 for (int i = n - 1;i >= 0;i--) 25 suf[i] = suf[i + 1] * (x - i) % mo; 26 ll ans = 0; 27 for (int i = 0;i <= n;i++) 28 { 29 ll tans = (n - i) & 1 ? -y[i] : y[i]; 30 if (i >= 1) 31 tans = (tans * pre[i - 1] % mo + mo) % mo; 32 if (i <= n - 1) 33 tans = (tans * suf[i + 1] % mo + mo) % mo; 34 tans = (tans * inv[n - i] % mo * inv[i] % mo + mo) % mo; 35 ans = (ans + tans) % mo; 36 } 37 return ans; 38 } 39 int main() 40 { 41 ll t = 1; 42 for (int i = 1;i <= 1000;i++) 43 t = t * i % mo; 44 inv[1000] = fpow(t,mo - 2); 45 for (int i = 999;i >= 0;i--) 46 inv[i] = inv[i + 1] * (i + 1) % mo; 47 for (scanf("%d",&T);T;T--) 48 { 49 scanf("%d%d",&n,&m); 50 for (int i = 0;i <= n;i++) 51 scanf("%lld",&y1[i]); 52 y1[n + 1] = calc(y1,n,n + 1); 53 for (int i = 1;i <= n + 1;i++) 54 y2[i] = y2[i - 1] + y1[i]; 55 int tl,tr; 56 for (int i = 1;i <= m;i++) 57 { 58 scanf("%d%d",&tl,&tr); 59 printf("%lld\n",((calc(y2,n + 1,tr) - calc(y2,n + 1,tl - 1)) % mo + mo) % mo); 60 } 61 } 62 return 0; 63 }
心之所动 且就随缘去吧