1 ~ n的k次方求和模板

∑ i = 1 n i k \sum\limits_{i = 1} ^{n} i ^ k i=1nik

/*
  Author : lifehappy
*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include 

using namespace std;

typedef long long ll;

const int inf = 0x3f3f3f3f;
const double eps = 1e-7;

const int N = 1e6 + 10, mod = 1e9 + 7;

ll fac[N], pre[N], suc[N], inv[N], prime[N], sum[N], n, k, cnt;

bool st[N];

ll quick_pow(ll a, int n) {
    ll ans = 1;
    while(n) {
        if(n & 1) ans = ans * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return ans;
}

void init() {
    sum[1] = 1;
    for(int i = 2; i < N; i++) {
        if(!st[i]) {
            prime[cnt++] = i;
            sum[i] = quick_pow(i, k);
        }
        for(int j = 0; j < cnt && i * prime[j] < N; j++) {
            st[i * prime[j]] = 1;
            sum[i * prime[j]] = 1ll * sum[i] * sum[prime[j]] % mod;
            if(i % prime[j] == 0) break;
        }
    }
    fac[0] = inv[0] = 1;
    for(int i = 1; i < N; i++) {
        sum[i] = (sum[i] + sum[i - 1]) % mod;
        fac[i] = 1ll * fac[i - 1] * i % mod;
    }
    inv[N - 1] = quick_pow(fac[N - 1], mod - 2);
    for(int i = N - 2; i >= 1; i--) {
        inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
    }
}

ll solve(ll n, int k) {
    ll ans = 0;
    init();
    pre[0] = suc[k + 3] = 1;
    for(int i = 1; i <= k + 2; i++) pre[i] = 1ll * pre[i - 1] * (n - i) % mod;
    for(int i = k + 2; i >= 1; i--) suc[i] = 1ll * suc[i + 1] * (n - i) % mod;
    for(int i = 1; i <= k + 2; i++) {
        ll a = 1ll * pre[i - 1] * suc[i + 1] % mod, b = 1ll * inv[i - 1] * inv[k + 2 - i] % mod;
        if((k + 2 - i) & 1) b *= -1;
        ans = ((ans + 1ll * sum[i] * a % mod * b % mod) % mod + mod) % mod;
    }
    return ans;
}

int main() {
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    scanf("%lld %lld", &n, &k);
    printf("%lld\n", solve(n, k));
	return 0;
}

你可能感兴趣的:(数论)