拉格朗日插值法--CF622F The Sum of the k-th Powers

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/84439704

传送门
注意到把 n n 作为 x i x_i i = 1 n i m \sum_{i=1}^ni^m 作为 y i y_i 这其实是一个 m + 1 m+1 次多项式,把前 m + 2 m+2 个点当成已知点,就可以拉格朗日插值法做了。
注意转移的时候乘除就好了,可以预处理前缀积和后缀积,把复杂度降下来。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 1000005
#define LL long long
using namespace std;
int n,m;
LL ans,mul1[maxn],mul2[maxn];
const int mod=1e9+7;

inline LL qpow(LL x,int k){
	LL ret=1;
	while(k){
		if(k&1) (ret*=x)%=mod;
		(x*=x)%=mod; k>>=1;
	} return ret%mod;
}

int main(){
	scanf("%d%d",&n,&m);
	if(n==1) return puts("1"),0;
	mul1[1]=n-1; mul2[m+2]=(n-m-2+mod)%mod; mul1[0]=mul2[m+3]=1;
	for(int i=2;i<=m+2;i++) mul1[i]=mul1[i-1]*(n-i+mod)%mod;
	for(int i=m+1;i>=1;i--) mul2[i]=mul2[i+1]*(n-i+mod)%mod;
	LL yi=0,fm=1;
	for(int i=2;i<=m+2;i++) fm=fm*(1-i+mod)%mod;
	for(int i=1;i<=m+2;i++){
		yi+=qpow(i,m)%mod; yi%=mod;
		LL fz=mul1[i-1]*mul2[i+1]%mod;
		if(i!=1) fm=fm*(i-1)%mod,fm=fm*qpow((i-m-3+mod)%mod,mod-2)%mod;
		(ans+=yi*fz%mod*qpow(fm,mod-2)%mod)%=mod;
	}
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sizeof_you/article/details/84439704