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

洛谷传送门

Codeforces传送门

题目大意

∑ i = 1 n i k m o d    ( 1 0 9 + 7 ) \sum_{i=1}^ni^k\mod (10^9+7) i=1nikmod(109+7) n ≤ 1 0 9 , k ≤ 1 0 6 ​ n\le 10^9,k\le 10^6​ n109,k106

解题分析

首先可以知道的是, 答案是一个 k + 1 k+1 k+1次, 关于 n n n的多项式, 于是我们只需要知道 k + 2 k+2 k+2项的值就好了。

考虑拉格朗日插值, 为了方便计算插前 k + 2 k+2 k+2个自然数:
f ( n ) = ∑ i = 1 k + 2 f ( i ) ∏ j ≠ i , j ∈ [ 1 , k + 2 ] n − j i − j f(n)=\sum_{i=1}^{k+2}f(i)\prod_{j\ne i,j\in[1,k+2]}\frac{n-j}{i-j} f(n)=i=1k+2f(i)j̸=i,j[1,k+2]ijnj
然后发现 i − j i-j ij无非是一段从 − 1 -1 1开始递减的序列的乘积和从 1 1 1开始递增的乘积, 上面可以预处理出所有的 n − i n-i ni的乘积然后乘上一个单独的逆元, f ( i ) f(i) f(i)可以 O ( N ) O(N) O(N)筛出来或偷懒 N l o g ( N ) Nlog(N) Nlog(N)算, 然后就做完了。

n ≤ k + 2 n\le k+2 nk+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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值