Skip to content

Commit c59cdc5

Browse files
committed
update
1 parent b5f6e9c commit c59cdc5

25 files changed

+460
-42
lines changed

.verify-helper/docs/index.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
[![Actions Status](https://github.com/KumaCS/library-cpp/workflows/verify/badge.svg)](https://github.com/KumaCS/library-cpp/actions)
2-
[![GitHub Pages](https://img.shields.io/static/v1?label=GitHub+Pages&message=+&color=brightgreen&logo=github)](https://KumaCS.github.io/library-cpp/)

data-structure/binary-indexed-tree.hpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ struct BinaryIndexedTree {
55
int size;
66
vector<T> data;
77
BinaryIndexedTree(int n) : size(n), data(n) {}
8-
T add(int p, T x) {
8+
void add(int p, T x) {
99
for (p++; p <= size; p += p & -p) data[p - 1] += x;
1010
}
1111
T sum(int p) {
@@ -15,9 +15,9 @@ struct BinaryIndexedTree {
1515
}
1616
T sum(int l, int r) { return sum(r) - sum(l); }
1717

18-
template <bool (*f)(S)>
18+
template <bool (*f)(T)>
1919
int lower_bound() const {
20-
return lower_bound([](S x) { return f(x); });
20+
return lower_bound([](T x) { return f(x); });
2121
}
2222
template <class F>
2323
int lower_bound(F f) const {
@@ -26,10 +26,8 @@ struct BinaryIndexedTree {
2626
while (r < size) r = r << 1;
2727
T s = 0;
2828
for (int len = r; len > 0; len >>= 1) {
29-
if (x + len < size && !f(s + data[x + len])) {
30-
s += data[x + len];
31-
x += len;
32-
}
29+
if (x + len < size && !f(s + data[x + len]))
30+
s += data[x += len];
3331
}
3432
return x + 1;
3533
}

data-structure/integer-set.hpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
template <class T = unsigned int, class U = unsigned long long>
3+
template <class T = int, class U = unsigned long long>
44
class IntegerSet {
55
private:
66
const static T B = 6, W = 64, MASK = W - 1;
@@ -24,11 +24,12 @@ class IntegerSet {
2424
while (n > 0);
2525
start = vector<T>(1, 0);
2626
start.reserve(len.size() + 1);
27-
for (const auto v : len) start.push_back(start.back() + v);
27+
for (auto v : len) start.push_back(start.back() + v);
2828
data = vector<U>(start.back());
2929
}
3030
IntegerSet(string s = "") {
31-
T n = size = s.size();
31+
size = s.size();
32+
T n = size;
3233
vector<T> len;
3334
do len.push_back((n >>= B) + 1);
3435
while (n > 0);
@@ -58,11 +59,11 @@ class IntegerSet {
5859
}
5960
}
6061
bool contains(T x) const { return (data[x >> B] >> (x & MASK)) & 1; }
61-
optional<T> min(T x) const {
62+
T min(T x) const {
6263
T d = 0, i = x;
6364
while (true) {
64-
if (d + 1 >= start.size()) return nullopt;
65-
if ((i >> B) >= start[d + 1] - start[d]) return nullopt;
65+
if (d + 1 >= start.size()) return -1;
66+
if ((i >> B) >= start[d + 1] - start[d]) return -1;
6667
U m = data[start[d] + (i >> B)] & ((~U(0)) << (i & MASK));
6768
if (m == 0) {
6869
d++;
@@ -77,11 +78,11 @@ class IntegerSet {
7778
}
7879
return i;
7980
}
80-
optional<T> max(T x) const {
81+
T max(T x) const {
8182
T d = 0, i = x;
8283
while (true) {
83-
if (i >= size) return nullopt;
84-
if (d >= data.size()) return nullopt;
84+
if (i < 0) return -1;
85+
if (d >= data.size()) return -1;
8586
U m = data[start[d] + (i >> B)] & ~((~U(1)) << (i & MASK));
8687
if (m == 0) {
8788
d++;

docs/flow/max-flow.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ push-relabel algorithm により $n$ 頂点 $m$ 辺のとき $O(n^2m)$ 時間.
88
- $\sum_{v\in V}f(v,u)-\sum_{v\in V}f(u,v)\geq 0$
99
- 頂点 $u$ の excess flow とは $e(u)=\sum_{v\in V}f(v,u)-\sum_{v\in V}f(u,v)$ のこと.
1010
- 頂点 $u$ が overflow しているとは $e(u)\gt 0$ であること.
11-
- height function $h:V\to\mathbb{N}$ は $h(s)=|V|,h(t)=0$ およびすべての残余辺 $(u,v)\in E_f$ に対し $h(u)\leq h(v)+1$ を満たすもの.
11+
- height function $h:V\to\mathbb{N}$ は $h(s)=\lvert V\rvert,h(t)=0$ およびすべての残余辺 $(u,v)\in E_f$ に対し $h(u)\leq h(v)+1$ を満たすもの.
1212

1313
preflow を更新する push,height function を更新する relabel を組み合わせたアルゴリズム.
1414

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
$n$ 次多項式 $f$ で $0\leq i\leq n$ に対し $f(x_i)=y_i$ を満たすものを $O(n(\log n)^2)$ 時間で求める.
2+
3+
## アルゴリズム
4+
5+
$g(x)=\prod_{i=0}^{n}(x-x_i)$ とすれば Lagrange 補間より以下が成り立つ.
6+
7+
$$f(x)=\sum_{i=0}^{n}\frac{y_ig(x)}{g'(x_i)(x-x_i)}$$
8+
9+
以下のようにして $O(n(\log n)^2)$ 時間で計算できる.
10+
11+
- $g(x)$ は分割統治により $O(n(\log n)^2)$ 時間で計算できる.
12+
- $g'(x_i)$ は多点評価により $O(n(\log n)^2)$ 時間で列挙できる.
13+
- $\sum_{i=0}^{n}\frac{y_i}{g'(x_i)(x-x_i)}$ は有理数の和として分割統治により $O(n(\log n)^2)$ 時間で計算できる.
14+
15+
$g(x)$ の計算過程はそれ以降にも流用できる.
Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,30 @@
1-
多項式 $f$ について $g(n)=\sum_{i=0}^{n-1}f(i)$ を満たす多項式 $g$ を求める.
1+
多項式 $f$ について $g(n)=\sum_{i=0}^{n}f(i)$ を満たす多項式 $g$ を求める.
2+
3+
$d=\deg f$ として $O(d\log d)$ 時間.
4+
5+
## アルゴリズム
6+
7+
Bernoulli 数 $B_i=\left[\frac{x^i}{i!}\right]\dfrac{xe^x}{e^x-1}$ を用いると以下が成り立つ.
8+
9+
$$\begin{align*}
10+
\sum_{i=1}^{n}i^k
11+
&=k![x^k]\sum_{i=1}^{n}e^{ix}\\
12+
&=k![x^k]\frac{(e^{nx}-1)e^x}{e^x-1}\\
13+
&=k![x^k]\frac{e^{nx}-1}{x}\cdot\frac{xe^x}{e^x-1}\\
14+
&=k!\sum_{i=0}^{k}\frac{n^{i+1}}{(i+1)!}\cdot\frac{B_{k-i}}{(k-i)!}
15+
\end{align*}$$
16+
17+
これは Faulhaber の公式として知られている.
18+
19+
$f(x)=\sum_{i=0}^{d-1}f_ix^i$ とすると,上の結果から $1\leq l\leq d$ に対して
20+
21+
$$\begin{align*}
22+
[x^l]g(x)
23+
&=\frac{1}{l!}\sum_{k=l-1}^{d-1}f_kk!\cdot\frac{B_{k-(l-1)}}{(k-(l-1))!}\\
24+
&=\frac{1}{l!}[x^{d-l}]\left(\sum_{i=0}^{d-1}f_ii!\cdot x^{d-1-i}\right)\frac{xe^x}{e^x-1}
25+
\end{align*}$$
26+
27+
が成り立つ.また $[x^0]g(x)=f_0$ であるから,結局 $g$ は $O(d\log d)$ 時間で計算できる.
28+
29+
- https://codeforces.com/blog/entry/98563
30+
- https://www.codechef.com/problems/SERSUM

docs/fps/product-of-polynomials.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
多項式 $f_1,f_2,\dots,f_n$ の総積を,次数の総和を $n$ として $O(n(\log n)^2)$ 時間で計算する.
2+
3+
分割統治すればよい.
4+
5+
## FFT 回数削減
6+
7+
それぞれを最低限の長さで FFT し,ダブリングをしていけばよい.

fps/fps-rational.hpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#pragma once
2+
#include "fps/formal-power-series.hpp"
3+
4+
template <class mint>
5+
struct FPSRational {
6+
using F = FormalPowerSeries<mint>;
7+
using R = FPSRational;
8+
F num, den;
9+
R& operator+=(const R& r) {
10+
num *= r.den;
11+
num += den * r.num;
12+
den *= r.den;
13+
return *this;
14+
}
15+
R& operator-=(const R& r) {
16+
num *= r.den;
17+
num -= den * r.num;
18+
den *= r.den;
19+
return *this;
20+
}
21+
R& operator*=(const R& r) {
22+
num *= r.num;
23+
den *= r.den;
24+
return *this;
25+
}
26+
R& operator/=(const R& r) {
27+
num *= r.den;
28+
den *= r.num;
29+
return *this;
30+
}
31+
R operator+(const R& r) const { return R(*this) += r; }
32+
R operator-(const R& r) const { return R(*this) -= r; }
33+
R operator*(const R& r) const { return R(*this) *= r; }
34+
R operator/(const R& r) const { return R(*this) /= r; }
35+
R inv() const { return {den, num}; }
36+
F approx(int deg) const { return (den * num.inv(deg)).pre(deg); }
37+
};

fps/polynomial-interpolation.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
#include "fps/formal-power-series.hpp"
3+
4+
template <class mint>
5+
FormalPowerSeries<mint> PolynomialInterpolation(const vector<mint>& x, const vector<mint>& y) {
6+
using fps = FormalPowerSeries<mint>;
7+
assert(x.size() == y.size());
8+
int n = x.size();
9+
if (n == 0) return {y[0]};
10+
vector<fps> prod(2 * n);
11+
for (int i = 0; i < n; i++) prod[i + n] = {-x[i], 1};
12+
for (int i = n - 1; i > 0; i--) prod[i] = prod[i * 2] * prod[i * 2 + 1];
13+
vector<fps> fs(2 * n);
14+
fs[1] = prod[1].diff();
15+
for (int i = 2; i < 2 * n; i++) fs[i] = fs[i / 2] % prod[i];
16+
for (int i = n; i < n * 2; i++) fs[i] = {y[i - n] / fs[i][0]};
17+
for (int i = n - 1; i > 0; i--) fs[i] = fs[(i << 1) | 0] * prod[(i << 1) | 1] + fs[(i << 1) | 1] * prod[(i << 1) | 0];
18+
return fs[1];
19+
}
20+
21+
/**
22+
* @brief 多項式補間
23+
* @docs docs/fps/polynomial-interpolation.md
24+
*/

fps/prefix-sum-of-polynomial.hpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
#pragma once
2+
#include "modint/factorial.hpp"
23
#include "fps/formal-power-series.hpp"
34

4-
// sum_{i=0}^{n-1}r^i*poly(i)
5-
// f[i]=poly(i)
5+
// g(n)=sum_{i=0}^{n}f(i)
66
template <class mint>
7-
mint SumOfExpPoly(long long n, mint r, vector<mint>& f) {
7+
FormalPowerSeries<mint> PrefixSumOfPolynomial(FormalPowerSeries<mint> f) {
8+
if (f.empty()) return {};
9+
using fact = Factorial<mint>;
10+
mint c = f[0];
811
int d = f.size();
9-
mint p = 1;
10-
vector<mint> g(d + 1, 0);
11-
for (int i = 0; i < d; i++) {
12-
g[i + 1] = g[i] + f[i] * p;
13-
p *= r;
14-
}
15-
16-
return s;
12+
fact::reserve(d);
13+
for (int i = 0; i < d; i++) f[i] *= fact::fact(i);
14+
reverse(f.begin(), f.end());
15+
FormalPowerSeries<mint> g(d);
16+
for (int i = 0; i < d; i++) g[i] = fact::fact_inv(i + 1) * (i & 1 ? -1 : 1);
17+
f *= g.inv();
18+
f.resize(d);
19+
f.push_back(c);
20+
reverse(f.begin(), f.end());
21+
for (int i = 1; i <= d; i++) f[i] *= fact::fact_inv(i);
22+
return f;
1723
}
1824
/**
19-
* @brief Prefix Sum of Polynomial
25+
* @brief 多項式の Prefix Sum
2026
* @docs docs/fps/prefix-sum-of-polynomial.md
2127
*/

0 commit comments

Comments
 (0)