【CF622F】自然數冪前綴和 + 拉格朗日插值法

題目大意是求:\sum_{i = 1}^ni^k = 1^k + 2^k + ... + n^k對 10^9 + 7 取模。

當 k = 1時,

當 k = 2時,

當 k = 3時,

我們可以發現所求答案爲k+1次多項式。我們只需要計算出k+2個點,然後應用拉格朗日插值法就可以得到此多項式。

#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 8;
const ll mod = 1e9 + 7;
ll n, k, f[maxn], fact[maxn];
ll power(ll a, ll b)
{
	ll ans = 1;
	a %= mod;
	while(b) {
		if(b & 1) ans = (ans * a) % mod;
		a = (a * a) % mod;
		b >>= 1;
	}
	return ans;
}
int main()
{
	while(scanf("%lld %lld", &n, &k) == 2) {
		f[0] = 0;
		for(int i = 1; i <= k+2; i++) f[i] = (f[i-1] + power(i, k)) % mod;
		if(n <= k+2) {
			printf("%lld\n", f[n]);
			continue;
		}
		fact[0] = 1;
		for(int i = 1; i <= k+2; i++) fact[i] = (fact[i-1] * i) % mod;
		ll cur = 1;
		for(int i = 1; i <= k+2; i++) cur = (cur * (n-i)) % mod;
		ll ans = 0;
		ll sign = 1;
		for(int i = 1; i <= k+2; i++) {
			ll inv1 = power(n-i, mod-2) % mod;
			ll inv2 = power(fact[i-1] % mod * fact[k+2-i] % mod, mod-2);
			if((k+2-i) & 1) sign = -1;
			else sign = 1;
			ans = (ans + sign * inv1 * inv2 % mod * cur % mod * f[i] % mod) % mod;
		}
		ans = (ans + mod) % mod;
		printf("%lld\n", ans);
	}
	return 0;
}
  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章