基准时间限制: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\n",ans); } return 0; }