[Educational Codeforces Round 7] - F The Sum of the k-th Powers

洛谷傳送門

Codeforces傳送門

題目大意

i=1nikmod  (109+7)\sum_{i=1}^ni^k\mod (10^9+7)n109,k106n\le 10^9,k\le 10^6​

解題分析

首先可以知道的是, 答案是一個k+1k+1次, 關於nn的多項式, 於是我們只需要知道k+2k+2項的值就好了。

考慮拉格朗日插值, 爲了方便計算插前k+2k+2個自然數:
f(n)=i=1k+2f(i)ji,j[1,k+2]njij f(n)=\sum_{i=1}^{k+2}f(i)\prod_{j\ne i,j\in[1,k+2]}\frac{n-j}{i-j}
然後發現iji-j無非是一段從1-1開始遞減的序列的乘積和從11開始遞增的乘積, 上面可以預處理出所有的nin-i的乘積然後乘上一個單獨的逆元, f(i)f(i)可以O(N)O(N)篩出來或偷懶Nlog(N)Nlog(N)算, 然後就做完了。

nk+2n\le k+2的時候暴力算就好了, 否則會搞出0來。

代碼如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define MOD 1000000007
#define MX 1005000
#define gc getchar()
#define ll long long
IN int fpow(R int base, R int tim)
{
	int ret = 1;
	W (tim)
	{
		if (tim & 1) ret = 1ll * ret * base % MOD;
		base = 1ll * base * base % MOD, tim >>= 1;
	}
	return ret;
}
IN void add(int &tar, R int ad) {tar += ad; if (tar >= MOD) tar -= MOD;}
int n, bd, k, all, sum, ans;
int pos[MX], neg[MX];
int main(void)
{
	scanf("%d%d", &n, &k); bd = k + 2;
	if (n <= bd)
	{
		for (R int i = 1; i <= n; ++i) add(sum, fpow(i, k));
		printf("%d\n", sum); return 0;
	}
	pos[0] = neg[0] = all = 1;
	for (R int i = 1; i <= bd; ++i) all = 1ll * all * (n - i) % MOD;
	for (R int i = 1; i <= bd; ++i) pos[i] = 1ll * pos[i - 1] * i % MOD;
	for (R int i = 1; i <= bd; ++i) neg[i] = 1ll * neg[i - 1] * (MOD - i) % MOD;
	for (R int i = 1; i <= bd; ++i)
	{
		add(sum, fpow(i, k));
		add(ans, 1ll * sum * all % MOD * fpow(n - i, MOD - 2) % MOD * fpow(neg[bd - i], MOD - 2) % MOD * fpow(pos[i - 1], MOD - 2) % MOD);
	}
	printf("%d\n", ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章