洛谷傳送門
Codeforces傳送門
題目大意
求,
解題分析
首先可以知道的是, 答案是一個次, 關於的多項式, 於是我們只需要知道項的值就好了。
考慮拉格朗日插值, 爲了方便計算插前個自然數:
然後發現無非是一段從開始遞減的序列的乘積和從開始遞增的乘積, 上面可以預處理出所有的的乘積然後乘上一個單獨的逆元, 可以篩出來或偷懶算, 然後就做完了。
當的時候暴力算就好了, 否則會搞出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);
}