51nod 1258 序列求和 V4

题目描述

T(n) = n^k,S(n) = T(1) + T(2) + ...... T(n)。给出n和k,求S(n)。
 
例如k = 2,n = 5,S(n) = 1^2 + 2^2 + 3^2 + 4^2 + 5^2 = 55。
由于结果很大,输出S(n) Mod 1000000007的结果即可。

Input

第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 500)
第2 - T + 1行:每行2个数,N, K中间用空格分割。(1 <= N <= 10^18, 1 <= K <= 50000)

Output

共T行,对应S(n) Mod 1000000007的结果。

Input示例

3
5 3
4 2
4 1

Output示例

225
30
10

Solution

很裸的一道自然数幂和问题。 我是用的是拉格朗日插值法
已知一个最高次项为n的多项式,已知n+1个点就能求得其解析式。
考虑构造多项式使其满足函数经过(x0,y0),(x1,y1),(x2,y2)...(xn+1,yn+1).

其中g(x)为n次多项式,显然要使其成立则
可推得
把要求的k带入函数中就可求出其自然数幂和

Code

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 typedef long long LL;
 9 
10 const int N=50005;
11 const int MOD=1000000007;
12 
13 int k,a[N],ny[N],pow[N],p[N],q[N];
14 LL n;
15 
16 int ksm(int x,int y)
17 {
18     int ans=1;
19     while (y)
20     {
21         if (y&1) ans=(LL)ans*x%MOD;
22         x=(LL)x*x%MOD;y>>=1;
23     }
24     return ans;
25 }
26 
27 int solve(LL x)
28 {
29     if (x<=k+2) return a[x];
30     x%=MOD;
31     int w=ksm(pow[k+2],MOD-2);LL ans=0;
32     p[0]=q[k+3]=1;
33     for (int i=1;i<=k+2;i++) p[i]=(LL)p[i-1]*(x-i)%MOD;
34     for (int i=k+2;i>=1;i--) q[i]=(LL)q[i+1]*(x-i)%MOD;
35     for (int i=1;i<=k+2;i++)
36     {
37         (ans+=(LL)a[i]*w%MOD*p[i-1]%MOD*q[i+1])%=MOD;
38         w=(LL)w*(i-k-2)%MOD*ny[i]%MOD;
39     }
40     ans+=ans<0?MOD:0;
41     return ans;
42 }
43 
44 int main()
45 {
46     int T;
47     scanf("%d",&T);
48     for (int i=1;i<=50002;i++) ny[i]=ksm(i,MOD-2);
49     pow[1]=1;
50     for (int i=2;i<=50002;i++) pow[i]=(LL)pow[i-1]*(1-i)%MOD;
51     while (T--)
52     {
53         scanf("%lld%d",&n,&k);
54         for (int i=1;i<=k+2;i++) a[i]=a[i-1]+ksm(i,k),a[i]-=a[i]>=MOD?MOD:0;
55         printf("%d\n",solve(n));
56     }
57     return 0;
58 }

 

 

posted @ 2017-11-23 17:17  _patrick  阅读(282)  评论(0编辑  收藏  举报