基准时间限制:8 秒 空间限制:131072 KB 分值: 1280 难度:9级算法题
Discription
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
拉格朗日插值模板题,但是要注意当 N%1e9+7 <= L 的时候,插的值里面只有一项不是0,这时候要特判一下。。
然后我们就水了1280分
/*
自然幂数和的拉格朗日插值做法。
假设我们求的是k次前缀和,那么就是一个k+1次多项式,
于是我们带k+2个点进去差值就好了。
f(x) = ∑y[i] * π(x-x[j]) / π(x[i]-x[j])
*/
#include<bits/stdc++.h>
#define ll long long
const int ha=1000000007;
using namespace std;
int T,K,L,ans=0,S;
int base,jc[50020];
ll N;
inline int add(int x,int y){
x+=y;
return x>=ha?x-ha:x;
}
inline int ksm(int x,int y){
int an=1;
for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
return an;
}
inline void solve(){
ans=S=0,base=1;
int ops=N%ha;
for(int i=1;i<=L;i++){
ops=add(ops,ha-1);
base=base*(ll)ops%ha;
}
if(!base){
ops=N%ha;
base=1;
for(int i=1;i<=L;i++){
ops=add(ops,ha-1);
S=add(S,ksm(i,K));
if(ops) base=base*(ll)ops%ha;
else ans=S*(ll)jc[i-1]%ha*(ll)jc[L-i]%ha*(ll)(((L-i)&1)?ha-1:1)%ha;
}
ans=ans*(ll)base%ha;
}
else{
ops=N%ha;
for(int i=1,now;i<=L;i++){
ops=add(ops,ha-1);
S=add(S,ksm(i,K));
now=base*(ll)ksm(ops,ha-2)%ha*(ll)jc[i-1]%ha*(ll)jc[L-i]%ha;
if((L-i)&1) now=now*(ll)(ha-1)%ha;
ans=add(ans,S*(ll)now%ha);
}
}
}
int main(){
jc[0]=1;
for(int i=1;i<=50010;i++) jc[i]=jc[i-1]*(ll)i%ha;
for(int i=1;i<=50010;i++) jc[i]=ksm(jc[i],ha-2);
scanf("%d",&T);
while(T--){
scanf("%lld%d",&N,&K),L=K+2;
solve();
printf("%d
",ans);
}
return 0;
}