Codeforces 622 F. The Sum of the k-th Powers

## [$>Codeforces space 622 F. The Sum of the k-th Powers<$](http://codeforces.com/problemset/problem/622/F)

题目大意 : 给出 (n, k),求 (sum_{i=1}^{n} i^k)(10^9 +7) 取模的值

(1 leq n leq 10^9, 0 leq k leq 10^6)

解题思路 :

考虑 (k) 比较大,且模数不太好 (NTT),于是考虑插值做法, 学习了一波插值之后,发现就是个板子题 (雾)

拉格朗日插值:

对于 (n) 个点值表达,可以确定一个 (n - 1) 次的多项式,考虑已知点值怎么构造这个多项式

如果对于第 (i) 个点值,能够构造出这么一个多项式 (f_i(x)) ,将每一个点值表达 (j) 带进去的结果如下

[f_i (x) = egin{cases} y_i , & ext{if $ i= j$} \ 0. \, & ext{otherwise} end{cases} ]

那么最终的多项式 (F(x) = sum_{i=1}^{n} f_i(x))

通过贺资料发现当 $f_i(x) = y_i imes prod_{j=1, j eq i}^{n} frac{x-x_j}{x_i-x_j} $ 时即可满足条件,不妨证明一下为什么

考虑分子部分,如果带进去的 (x eq x_i) 那么当 (j = i) 的时候分子是 (0),结果也是 (0)

考虑分母部分,如果 (x = x_i) 那么分子就等于分母,且分子分母都不存在 (0) ,所以结果就是 (y_i)

大力观察题面发现,(k) 次幂的前缀和一定能用一个 (k + 1) 次的多项式来表示,不妨递推出 (x = 1 .. (k+2)) 时的点值表示直接做插值

那么第 (n) 项的答案就等于 $F(n) = sum y_i imes prod_{j=1, j eq i}^{k+2} frac{n-x_j}{x_i-x_j} $

因为 (x_i = i) ,所以 (F(n) = sum y_i imes prod_{j=1, j eq i}^{k+2} frac{n-j}{i-j}), 后面部分也就是 (frac{(n-1) imes(n-2) imes.. imes(n-k-2)}{(n-i) imes(i-1)! imes(n-i)! imes (-1)^{n-i}})

那么阶乘与处理一下枚举一下 (i) 即可,注意特判一下 (i = n) 的情况不能直接除,应该记一个没有 ((n-i)) 这一项的答案


/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
    int f = 0, ch = 0; x = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    if(f) x = -x;
}
#define int ll
int js[2000005], n, k;
const int Mod = 1000000007; 
inline int Pow(int a, int b){
	int ans = 1;
	for(; b; b >>= 1, a = a * a % Mod)
		if(b & 1) ans = ans * a % Mod;
	return ans;
}
inline int Inv(int x){ return Pow((x + Mod) % Mod, Mod - 2); } 
main(){
	int res = 1, res2 = 1; read(n), read(k), js[0] = 1; 
	for(int i = 1; i <= k + 2; i++){
		js[i] = (js[i-1] * i) % Mod;
		res = (res * (n - i) + Mod) % Mod;
		if(i != n) res2 = (res2 * (n - i) % Mod + Mod) % Mod;
	}
	int now = 0, ans = 0;
	for(int i = 1; i <= k + 2; i++){
		now = (now + Pow(i, k)) % Mod;
		int A = (i != n) ? res * Inv(n - i) % Mod : res2;
		int B = js[i-1] * js[k+2-i] % Mod;
		if((k + 2 - i) & 1) B = (-B + Mod) % Mod;
		ans = (ans + now * (A * Inv(B) % Mod) % Mod) % Mod;
	}
	cout << (ans % Mod + Mod) % Mod; 
	return 0;
}
原文地址:https://www.cnblogs.com/mangoyang/p/9398179.html