The Sum of the k-th Powers

link

慢慢推式子,顺便理清思路。

首先这个式子是一个 k+1 次多项式,而拉格朗日差值是可以做这种给定 k+2 个点然后求在这条曲线上另一个点纵坐标的事情的。

方便起见直接用 [1,k+2] 的函数值来做。假如某处的函数值为 s(i) ,由拉插的公式可得:

f(m)=i=1k+2sijimjij=i=1k+2siji(mj)ji(ij)

O(N2)会当场去世,考虑优化。

会发现 si 似乎并没有办法优化,所以求和部分是硬消耗,于是考虑如何快速求得后面那个分式的值。

于是惊奇而又开心地发现分子分母都是等差数列,而且是连续整数的乘积。于是分别分析。分子部分:

ji(mj)=j=1i1(mj)j=i+1k+2(mj)

可以考虑维护 mj 的前缀后缀积(后缀的话从 j=k+2 开始),即可快速求解。分子部分则更加简单:

ss(i)=j=1ij

ji(ij)=j=1i1jj=ik21j=ss(i1)ss(k+2i)(1)k+21

于是就都可以预处理啦。

代码异常简洁(核心代码不到200字),跑得也很快。写得很顺,开心快乐。

#include<cstdio>
#define zczc
#define int long long
const int N=1000010;
const int mod=1e9+7;
inline void read(int &wh){
	wh=0;int f=1;char w=getchar();
	while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
	while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
	wh*=f;return;
}

inline int pow(int s1,int s2){
	if(s2==1)return s1;
	if(s2==0)return 1;
	int an=pow(s1,s2>>1);
	if(s2&1)return an*an%mod*s1%mod;
	else return an*an%mod;
}

int m,k,sum,ans,a[N],b[N],c[N];

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(k);
	
	a[0]=b[0]=c[k+3]=1;
	for(int i=1;i<=k+2;i++)a[i]=a[i-1]*i%mod;
	for(int i=1;i<=k+2;i++)b[i]=b[i-1]*(m-i)%mod;
	for(int i=k+2;i;i--)c[i]=c[i+1]*(m-i)%mod;
	
	for(int i=1;i<=k+2;i++){
		sum+=pow(i,k);sum%=mod;
		int u=b[i-1]*c[i+1]%mod;
		int v=a[i-1]*a[k+2-i]*((k-i)%2?-1:1)%mod;
		ans+=sum*u%mod*pow(v,mod-2)%mod;ans%=mod;
	}
	printf("%lld",(ans+mod)%mod);
	
	return 0;
}
posted @   Feyn618  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示