codeforces 622f

第一道拉格朗日插值
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int maxn = 1000006;
const LL mod = 1e9 + 7;
int n, k;
LL po[maxn];//prod_i(1~maxn)
LL ne[maxn];//prod_i (-1~-maxn)
LL c[maxn];//系数 po[i-1]*ne[i-k-2]
LL S, Y[maxn];
LL x, y;
LL ex_gcd(LL num1, LL num2)
{
	if (!num2)
	{
		x = 1;
		y = 0;
		return num1;
	}
	LL ans = ex_gcd(num2, num1%num2);
	LL tmp = x;
	x = y;
	y = tmp - (num1 / num2)*x;
	return ans;
}
LL inv(LL xx){
	ex_gcd(xx, mod);
	return (x % mod + mod) % mod;
}
void pre(){
	po[0] = ne[0] = 1;
	for (int i = 1; i <= k + 2; i++){
		int x = mod - i;
		po[i] = (po[i - 1] * i) % mod;
		ne[i] = (ne[i - 1] * x) % mod;
	}
	for (int i = 1; i <= k + 2; i++){
		c[i] = (inv(po[i - 1]) * inv(ne[k + 2 - i])) % mod;
	}
	S = 1;
	for (int i = n - k - 2; i <= n - 1; i++){
		S = (S*i) % mod;
	}
}
LL pow(LL a, int k){
	LL ret = 1;
	while (k){
		if (k & 1) ret = (ret * a) % mod;
		a = (a * a) % mod;
		k >>= 1;
	}
	return ret;
}
int main(){
	cin >> n >> k;
	if (!k){
		cout << n << endl;
		return 0;
	}
	for (int i = 1; i <= min(k + 2, n); i++){
		Y[i] = (Y[i - 1] + pow(i*1LL, k)) % mod;
	}
	if (n <= k + 2){
		printf("%d\n", Y[n]);
		return 0;
	}
	pre();
	LL ret = 0;
	for (int i = 1; i <= k + 2; i++){
		LL mid = (((c[i] * S) % mod) * Y[i])%mod;
		ret = (ret + mid * inv(n - i)) % mod;
	}
	cout << ret << endl;
	return 0;
}

你可能感兴趣的:(codeforces 622f)