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) = \begin{cases} y_i , & \text{if $ i= j$} \\ 0. \, & \text{otherwise} \end{cases} \]

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

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

考虑分子部分,如果带进去的 \(x \neq 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 \times \prod_{j=1, \ j \neq i}^{k+2} \frac{n-x_j}{x_i-x_j} $

因为 \(x_i = i\) ,所以 \(F(n) = \sum y_i \times \prod_{j=1, \ j \neq i}^{k+2} \frac{n-j}{i-j}\), 后面部分也就是 \(\frac{(n-1)\times(n-2)\times..\times(n-k-2)}{(n-i)\times(i-1)!\times(n-i)!\times (-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;
}
posted @ 2018-07-31 20:47  Joyemang33  阅读(256)  评论(1编辑  收藏  举报