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 }