51NOD 1258 序列求和 V4

Posted 蒟蒻JHY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51NOD 1258 序列求和 V4相关的知识,希望对你有一定的参考价值。

基准时间限制: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;
}

  

 





以上是关于51NOD 1258 序列求和 V4的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1258 序列求和 V4

bzoj 1258 序列求和 V4

51nod1229 序列求和 V2

51nod1236 序列求和 V3 数学

51nod1229 序列求和 V2 数学

51nod 1228 序列求和