1. 程式人生 > >拉格朗日插值法--CF622F The Sum of the k-th Powers

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

傳送門
注意到把 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;
}