File tree Expand file tree Collapse file tree 3 files changed +83
-0
lines changed
Expand file tree Collapse file tree 3 files changed +83
-0
lines changed Original file line number Diff line number Diff line change 1+ #pragma once
2+ #include < vector>
3+
4+ // Computes the sum of the k-th powers
5+ // Complexity:
6+ // - O(k) per query,
7+ // - O(k^2) precomputation (can be reduced to O(k log k) with FFT)
8+ template <class MODINT > struct kth_power_sum {
9+
10+ // generating function: x / (e^x - 1) + x
11+ // NOTE: use B(1) = 1/2 definition
12+ std::vector<MODINT> bernoulli;
13+
14+ kth_power_sum () = default ;
15+
16+ void expand () {
17+ if (bernoulli.empty ()) {
18+ bernoulli = {1 };
19+ } else {
20+ const int k = bernoulli.size ();
21+ MODINT x (0 );
22+ for (int i = 0 ; i < k; ++i) { x = -x + bernoulli[i] * MODINT::binom (k + 1 , i); }
23+ bernoulli.push_back (x / (k + 1 ));
24+ }
25+ }
26+
27+ // Calculate 1^k + 2^k + ... + n^k
28+ // Based on Faulhaber's formula:
29+ // S_k(n) = 1 / (k + 1) * sum_{j=0}^{k} B_j * C(k + 1, j) * n^(k + 1 - j)
30+
31+ template <class T > MODINT prefix_sum (int k, const T &n) {
32+ while ((int )bernoulli.size () <= k) expand ();
33+
34+ MODINT ret (0 ), np (1 );
35+ for (int j = k; j >= 0 ; --j) {
36+ np *= n;
37+ ret += MODINT::binom (k + 1 , j) * bernoulli[j] * np;
38+ }
39+ return ret / (k + 1 );
40+ }
41+ };
Original file line number Diff line number Diff line change 1+ ---
2+ title : Sum of $k$-th powers of first $n$ positive integers (自然数の $k$ 乗和)
3+ documentation_of : ./kth_power_sum.hpp
4+ ---
5+
6+ 「 $1$ 以上 $n$ 以下の自然数の $k$ 乗の総和」を Faulhaber の公式を用いて計算する.
7+
8+ 内部で Bernoulli 数の先頭 $k + 1$ 項を計算する必要がある.このコードでは ` prefix_sum() ` メンバ関数が呼ばれた時点で動的に不足している部分を計算し, $\Theta(k^2)$ で動く.より高速にする必要があれば,母関数 $x / (\exp(x) - 1) + x$ (第 1 項の定義に $+1/2$ を採用している点に注意)の冪級数展開を FFT 等で計算してメンバ変数 ` bernoulli ` に事前に設定しておけばよい.
9+
10+ ## 使用方法
11+
12+ ``` cpp
13+ using mint = ModInt<998244353 >;
14+ kth_power_sum<mint> kp;
15+
16+ int k = 1 ;
17+ long long n = 10 ;
18+
19+ auto sum = kp.prefix_sum(k, n); // 1^k + ... + n^k
20+
21+ assert (sum == mint(55 ));
22+ ```
23+
24+ ## 問題例
25+
26+ - [ No.665 Bernoulli Bernoulli - yukicoder] ( https://yukicoder.me/problems/no/665 )
27+ - [ Educational Codeforces Round 7 F. The Sum of the k-th Powers - Codeforces] ( https://codeforces.com/contest/622/problem/F )
Original file line number Diff line number Diff line change 1+ #define PROBLEM " https://yukicoder.me/problems/no/665"
2+ #include " ../kth_power_sum.hpp"
3+ #include " ../../modint.hpp"
4+ #include < iostream>
5+ using namespace std ;
6+
7+ int main () {
8+ long long n;
9+ int k;
10+ cin >> n >> k;
11+
12+ kth_power_sum<ModInt<1000000007 >> kps;
13+
14+ cout << kps.prefix_sum (k, n) << ' \n ' ;
15+ }
You can’t perform that action at this time.
0 commit comments