0% found this document useful (0 votes)
31 views26 pages

kactl

The document outlines various strategies and considerations for preparing for programming contests, including debugging techniques, algorithm efficiency, and handling edge cases. It emphasizes the importance of testing, understanding problem statements, and optimizing memory usage. Additionally, it provides mathematical formulas and concepts relevant to problem-solving in competitive programming.

Uploaded by

navinp1281
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views26 pages

kactl

The document outlines various strategies and considerations for preparing for programming contests, including debugging techniques, algorithm efficiency, and handling edge cases. It emphasizes the importance of testing, understanding problem statements, and optimizing memory usage. Additionally, it provides mathematical formulas and concepts relevant to problem-solving in competitive programming.

Uploaded by

navinp1281
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

KTH Royal Institute of Technology

Omogen Heap
Simon Lindholm, Johan Sannemo, Mårten Wiman

2024-11-24
1 Contest 1 troubleshoot.txt 52 lines
ed − bf
Pre-submit:
ax + by = e x=
2 Mathematics 1 Write a few simple test cases if sample is not enough. ad − bc

Are time limits close? If so, generate max cases. cx + dy = f af − ec
Is the memory usage fine? y=
3 Data structures 3 Could anything overflow? ad − bc
Make sure to submit the right file.
In general, given an equation Ax = b, the solution to a variable
4 Numerical 5 Wrong answer: xi is given by
Print your solution! Print debug output, as well.
det A′i
5 Number theory 8 Are you clearing all data structures between test cases? xi =
Can your algorithm handle the whole range of input? det A
Read the full problem statement again.
6 Combinatorial 10 Do you handle all corner cases correctly?
where A′i is A with the i’th column replaced by b.
Have you understood the problem correctly?
Any uninitialized variables?
2.2 Recurrences
7 Graph 11 Any overflows? If an = c1 an−1 + · · · + ck an−k , and r1 , . . . , rk are distinct roots of
Confusing N and M, i and j, etc.?
Are you sure your algorithm works?
xk − c1 xk−1 − · · · − ck , there are d1 , . . . , dk s.t.
8 Geometry 16 What special cases have you not thought of?
Are you sure the STL functions you use work as you think? an = d1 r1n + · · · + dk rkn .
9 Strings 20 Add some assertions, maybe resubmit.
Create some testcases to run your algorithm on. Non-distinct roots r become polynomial factors, e.g.
Go through the algorithm for a simple case. an = (d1 n + d2 )rn .
10 Various 22 Go through this list again.
Explain your algorithm to a teammate.
Ask the teammate to look at your code.
2.3 Trigonometry
Contest (1) Go for a small walk, e.g. to the toilet.
Is your output format correct? (including whitespace) sin(v + w) = sin v cos w + cos v sin w
Rewrite your solution from the start or let a teammate do it.
cos(v + w) = cos v cos w − sin v sin w
template.cpp 14 lines
Runtime error:
#include <bits/stdc++.h> Have you tested all corner cases locally?
using namespace std; Any uninitialized variables?
Are you reading or writing outside the range of any vector? tan v + tan w
#define rep(i, a, b) for(int i = a; i < (b); ++i) Any assertions that might fail? tan(v + w) =
#define all(x) begin(x), end(x) Any possible division by 0? (mod 0 for example) 1 − tan v tan w
#define sz(x) (int)(x).size() Any possible infinite recursion? v+w v−w
typedef long long ll; Invalidated pointers or iterators? sin v + sin w = 2 sin cos
typedef pair<int, int> pii; Are you using too much memory?
2 2
typedef vector<int> vi; Debug with resubmits (e.g. remapped signals, see Various). v+w v−w
cos v + cos w = 2 cos cos
2 2
int main() { Time limit exceeded:
cin.tie(0)->sync_with_stdio(0); Do you have any possible infinite loops? (V + W ) tan(v − w)/2 = (V − W ) tan(v + w)/2
cin.exceptions(cin.failbit); What is the complexity of your algorithm?
} Are you copying a lot of unnecessary data? (References) where V, W are lengths of sides opposite angles v, w.
How big is the input and output? (consider scanf)
Avoid vector, map. (use arrays/unordered_map) a cos x + b sin x = r cos(x − ϕ)
.bashrc 3 lines What do your teammates think about your algorithm?
alias c=’g++ -Wall -Wconversion -Wfatal-errors -g -std=c++17 \
a sin x + b cos x = r sin(x + ϕ)
-fsanitize=undefined,address’ Memory limit exceeded: √
xmodmap -e ’clear lock’ -e ’keycode 66=less greater’ #caps = <> What is the max amount of memory your algorithm should need? where r = a2 + b2 , ϕ = atan2(b, a).
Are you clearing all data structures between test cases?
2.4 Geometry
.vimrc 6 lines
2.4.1 Triangles
set cin aw ai is ts=4 sw=4 tm=50 nu noeb bg=dark ru cul
sy on | im jk <esc> | im kj <esc> | no ; :
Mathematics (2) Side lengths: a, b, c
" Select region and then type :Hash to hash your selection. a+b+c
Semiperimeter: p =
" Useful for verifying that there aren’t mistypes.
ca Hash w !cpp -dD -P -fpreprocessed \| tr -d ’[:space:]’ \
2.1 Equations p 2
Area: A = p(p − a)(p − b)(p − c)
\| md5sum \| cut -c-6 √ abc
2 −b ± b2 − 4ac Circumradius: R =
ax + bx + c = 0 ⇒ x = 4A
hash.sh 3 lines
2a A
Inradius: r =
# Hashes a file, ignoring all whitespace and comments. Use for p
# verifying that code was correctly typed. Length √of median (divides triangle into two equal-area triangles):
cpp -dD -P -fpreprocessed | tr -d ’[:space:]’| md5sum |cut -c-6
The extremum is given by x = −b/2a. ma = 12 2b2 + 2c2 − a2
KTH template .bashrc .vimrc hash troubleshoot 2
Length
v of "bisector (divides angles in two): 2.6 Sums First success distribution
u 2 # a a+1 b cb+1 − ca
The number of trials needed to get the first success in

u a c +c + ··· + c = , c ̸= 1
sa = tbc 1 − c−1 independent yes/no experiments, each which yields success with
b+c
n(n + 1) probability p is Fs(p), 0 ≤ p ≤ 1.
sin α sin β sin γ 1 1 + 2 + 3 + ··· + n =
Law of sines: = = = 2
a b c 2R p(k) = p(1 − p)k−1 , k = 1, 2, . . .
Law of cosines: a2 = b2 + c2 − 2bc cos α 2 2 2 2 n(2n + 1)(n + 1)
1 + 2 + 3 + ··· + n =
α+β 6
a+b tan 1 2 1−p
Law of tangents: = 2 3 3 3 3 n2 (n + 1)2 µ= ,σ =
a−b α−β 1 + 2 + 3 + ··· + n = p p2
tan 4
2 n(n + 1)(2n + 1)(3n2 + 3n − 1)
2.4.2 Quadrilaterals 4 4 4 4
1 + 2 + 3 + ··· + n = Poisson distribution
With side lengths a, b, c, d, diagonals e, f , diagonals angle θ, area 30
The number of events occurring in a fixed period of time t if these
A and magic flux F = b2 + d2 − a2 − c2 : events occur with a known average rate κ and independently of
2.7 Series the time since the last event is Po(λ), λ = tκ.
x2 x3
ex = 1 + x +
p
4A = 2ef · sin θ = F tan θ = 4e2 f 2 − F 2 + + . . . , (−∞ < x < ∞) λk
2! 3! p(k) = e−λ , k = 0, 1, 2, . . .
x 2
x 3
x4 k!
ln(1 + x) = x − + − + . . . , (−1 < x ≤ 1)
For cyclic quadrilateralspthe sum of opposite angles is 180◦ , 2 3 4
ef = ac + bd, and A = (p − a)(p − b)(p − c)(p − d). √ x x2 2x3 5x4 µ = λ, σ 2 = λ
1+x=1+ − + − + . . . , (−1 ≤ x ≤ 1)
2.4.3 Spherical coordinates 2 8 32 128
3 5 7 2.8.2 Continuous distributions
x x x
z sin x = x − + − + . . . , (−∞ < x < ∞) Uniform distribution
3! 5! 7!
2 4 6
r cos x = 1 −
x
+
x

x
+ . . . , (−∞ < x < ∞)
If the probability density function is constant between a and b
y 2! 4! 6! and 0 elsewhere it is U(a, b), a < b.
2.8 Probability theory  1
a<x<b
x Let X be a discrete random variable with probability pX (x) of f (x) = b−a
0 otherwise
assuming theP value x. It will then have an expected value (mean)
µ = E(X) = x xpX (x) and variance
(b − a)2
p
σ 2 = V (X) = E(X 2 ) − (E(X))2 = x (x − E(X))2 pX (x) where σ a+b 2
2 + y2 + z2
P
x = r sin θ cos ϕ r = xp µ= ,σ =
y = r sin θ sin ϕ θ = acos(z/ x2 + y 2 + z 2 ) is the standard deviation. If X is instead continuous it will have 2 12
z = r cos θ ϕ = atan2(y, x) a probability density function fX (x) and the sums above will
Exponential distribution
instead be integrals with pX (x) replaced by fX (x).
The time between events in a Poisson process is
2.5 Derivatives/Integrals Expectation is linear: Exp(λ), λ > 0.
E(aX + bY ) = aE(X) + bE(Y ) λe−λx x ≥ 0

f (x) =
d 1 d 1 For independent X and Y , 0 x<0
arcsin x = √ arccos x = − √
dx 1 − x2 dx 1 − x2 V (aX + bY ) = a2 V (X) + b2 V (Y ). 1 2 1
d d 1 µ= ,σ = 2
tan x = 1 + tan2 x arctan x = λ λ
dx dx 1 + x2 2.8.1 Discrete distributions
Z
ln | cos ax|
Z
sin ax − ax cos ax Binomial distribution Normal distribution
tan ax = − x sin ax =
a a2 Most real random values with mean µ and variance σ 2 are well
√ ax The number of successes in n independent yes/no experiments,
described by N (µ, σ 2 ), σ > 0.
Z Z
−x2 π e
e = erf(x) xeax dx = 2 (ax − 1) each which yields success with probability p is
2 a Bin(n, p), n = 1, 2, . . . , 0 ≤ p ≤ 1.
1 (x−µ)2

! f (x) = √ e 2σ2
n k 2πσ 2
Integration by parts: p(k) = p (1 − p)n−k
k
If X1 ∼ N (µ1 , σ12 ) and X2 ∼ N (µ2 , σ22 ) then
Z b Z b µ = np, σ 2 = np(1 − p)
f (x)g(x)dx = [F (x)g(x)]ba − F (x)g ′ (x)dx Bin(n, p) is approximately Po(np) for small p. aX1 + bX2 + c ∼ N (µ1 + µ2 + c, a2 σ12 + b2 σ22 )
a a
KTH OrderStatisticTree HashMap SegmentTree LazySegmentTree UnionFindRollback SubMatrix 3
2.9 Markov chains Description: Hash map with mostly the same API as unordered map, but val = max(l->val, r->val);
∼3x faster. Uses 1.5x memory. Initial capacity must be a power of 2 (if }
A Markov chain is a discrete random process with the property provided). }
d77092, 7 lines
that the next state depends only on the current state. Let void add(int L, int R, int x) {
#include <bits/extc++.h> if (R <= lo || hi <= L) return;
X1 , X2 , . . . be a sequence of random variables generated by the // To use most b i t s rather than j u s t the lowest ones : if (L <= lo && hi <= R) {
Markov process. Then there is a transition matrix P = (pij ), struct chash { // large odd number for C if (mset != inf) mset += x;
with pij = Pr(Xn = i|Xn−1 = j), and p(n) = Pn p(0) is the const uint64_t C = ll(4e18 * acos(0)) | 71; else madd += x;
(n)
ll operator()(ll x) const { return __builtin_bswap64(x*C); } val += x;
probability distribution for Xn (i.e., pi = Pr(Xn = i)), where }; }
(0) __gnu_pbds::gp_hash_table<ll,int,chash> h({},{},{},{},{1<<16});
p is the initial distribution. else {
push(), l->add(L, R, x), r->add(L, R, x);
π is a stationary distribution if π = πP. If the Markov chain is SegmentTree.h val = max(l->val, r->val);
Description: Zero-indexed max-tree. Bounds are inclusive to the left and }
irreducible (it is possible to get to any state from any state), then exclusive to the right. Can be changed by modifying T, f and unit. }
πi = E(T1 i ) where E(Ti ) is the expected time between two visits in Time: O (log N ) 0f4bdb, 19 lines
void push() {
if (!l) {
state i. πj /πi is the expected number of visits in state j between struct Tree { int mid = lo + (hi - lo)/2;
two visits in state i. typedef int T; l = new Node(lo, mid); r = new Node(mid, hi);
static constexpr T unit = INT_MIN; }
T f(T a, T b) { return max(a, b); } // (any associative fn ) if (mset != inf)
For a connected, undirected and non-bipartite graph, where the vector<T> s; int n; l->set(lo,hi,mset), r->set(lo,hi,mset), mset = inf;
transition probability is uniform among all neighbors, πi is Tree(int n = 0, T def = unit) : s(2*n, def), n(n) {} else if (madd)
proportional to node i’s degree. void update(int pos, T val) { l->add(lo,hi,madd), r->add(lo,hi,madd), madd = 0;
for (s[pos += n] = val; pos /= 2;) }
s[pos] = f(s[pos * 2], s[pos * 2 + 1]); };
A Markov chain is ergodic if the asymptotic distribution is }
independent of the initial distribution. A finite Markov chain is T query(int b, int e) { // query [ b , e)
ergodic iff it is irreducible and aperiodic (i.e., the gcd of cycle T ra = unit, rb = unit; UnionFindRollback.h
for (b += n, e += n; b < e; b /= 2, e /= 2) { Description: Disjoint-set data structure with undo. If undo is not needed,
lengths is 1). limk→∞ Pk = 1π. if (b % 2) ra = f(ra, s[b++]); skip st, time() and rollback().
if (e % 2) rb = f(s[--e], rb); Usage: int t = uf.time(); ...; uf.rollback(t);
A Markov chain is an A-chain if the states can be partitioned } Time: O (log(N )) de4ad0, 21 lines
return f(ra, rb);
into two sets A and G, such that all states in A are absorbing }
struct RollbackUF {
(pii = 1), and all states in G leads to an absorbing state in A. vi e; vector<pii> st;
};
RollbackUF(int n) : e(n, -1) {}
The probability for absorption in state i ∈ A, when the initial int size(int x) { return -e[find(x)]; }
LazySegmentTree.h
P
state is j, is aij = pij + k∈G aik pkj . The expected
P time until
int find(int x) { return e[x] < 0 ? x : find(e[x]); }
absorption, when the initial state is i, is ti = 1 + k∈G pki tk . Description: Segment tree with ability to add or set values of large inter- int time() { return sz(st); }
vals, and compute max of intervals. Can be changed to other things. Use void rollback(int t) {
with a bump allocator for better performance, and SmallPtr or implicit in- for (int i = time(); i --> t;)
dices to save memory. e[st[i].first] = st[i].second;
Usage: Node* tr = new Node(v, 0, sz(v)); st.resize(t);
Data structures (3) Time: O (log N ). }
"../various/BumpAllocator.h" 34ecf5, 50 lines bool join(int a, int b) {
OrderStatisticTree.h const int inf = 1e9; a = find(a), b = find(b);
Description: A set (not multiset!) with support for finding the n’th ele- struct Node { if (a == b) return false;
ment, and finding the index of an element. To get a map, change null type. Node *l = 0, *r = 0; if (e[a] > e[b]) swap(a, b);
Time: O (log N ) int lo, hi, mset = inf, madd = 0, val = -inf; st.push_back({a, e[a]});
782797, 16 lines
Node(int lo,int hi):lo(lo),hi(hi){} // Large interval of =in f st.push_back({b, e[b]});
#include <bits/extc++.h> Node(vi& v, int lo, int hi) : lo(lo), hi(hi) { e[a] += e[b]; e[b] = a;
using namespace __gnu_pbds; if (lo + 1 < hi) { return true;
int mid = lo + (hi - lo)/2; }
template<class T> l = new Node(v, lo, mid); r = new Node(v, mid, hi); };
using Tree = tree<T, null_type, less<T>, rb_tree_tag, val = max(l->val, r->val);
tree_order_statistics_node_update>; }
else val = v[lo];
SubMatrix.h
void example() { Description: Calculate submatrix sums quickly, given upper-left and lower-
} right corners (half-open).
Tree<int> t, t2; t.insert(8); int query(int L, int R) {
auto it = t.insert(10).first; Usage: SubMatrix<int> m(matrix);
if (R <= lo || hi <= L) return -inf; m.sum(0, 0, 2, 2); // top left 4 elements
assert(it == t.lower_bound(9)); if (L <= lo && hi <= R) return val; Time: O N 2 + Q

assert(t.order_of_key(10) == 1); push(); c59ada, 13 lines
assert(t.order_of_key(11) == 2); return max(l->query(L, R), r->query(L, R)); template<class T>
assert(*t.find_by_order(0) == 8); } struct SubMatrix {
t.join(t2); // assuming T < T2 or T > T2, merge t2 into t void set(int L, int R, int x) { vector<vector<T>> p;
} if (R <= lo || hi <= L) return; SubMatrix(vector<vector<T>>& v) {
if (L <= lo && hi <= R) mset = val = x, madd = 0; int R = sz(v), C = sz(v[0]);
HashMap.h else { p.assign(R+1, vector<T>(C+1));
push(), l->set(L, R, x), r->set(L, R, x); rep(r,0,R) rep(c,0,C)
KTH Matrix LineContainer Treap FenwickTree FenwickTree2d RMQ 4
p[r+1][c+1] = v[r][c] + p[r][c+1] + p[r+1][c] - p[r][c]; isect(x, erase(y)); FenwickTree.h
} } Description: Computes partial sums a[0] + a[1] + ... + a[pos - 1], and
T sum(int u, int l, int d, int r) { ll query(ll x) { updates single elements a[i], taking the difference between the old and new
return p[d][r] - p[d][l] - p[u][r] + p[u][l]; assert(!empty()); value.
} auto l = *lower_bound(x); Time: Both operations are O (log N ). e62fac, 22 lines
}; return l.k * x + l.m;
} struct FT {
}; vector<ll> s;
Matrix.h FT(int n) : s(n) {}
Description: Basic operations on square matrices. void update(int pos, ll dif) { // a [ pos ] += d i f
Usage: Matrix<int, 3> A; Treap.h for (; pos < sz(s); pos |= pos + 1) s[pos] += dif;
A.d = {{{{1,2,3}}, {{4,5,6}}, {{7,8,9}}}}; Description: A short self-balancing tree. It acts as a sequential container }
vector<int> vec = {1,2,3}; with log-time splits/joins, and is easy to augment with additional data. ll query(int pos) { // sum of values in [0 , pos)
vec = (AˆN) * vec; Time: O (log N ) 9556fc, 55 lines ll res = 0;
c43c7d, 26 lines
struct Node { for (; pos > 0; pos &= pos - 1) res += s[pos-1];
template<class T, int N> struct Matrix { return res;
typedef Matrix M; Node *l = 0, *r = 0;
int val, y, c = 1; }
array<array<T, N>, N> d{}; int lower_bound(ll sum) {// min pos s t sum of [0 , pos ] >= sum
Node(int val) : val(val), y(rand()) {}
M operator*(const M& m) const {
void recalc(); // Returns n i f no sum i s >= sum, or =1 i f empty sum i s .
M a; if (sum <= 0) return -1;
rep(i,0,N) rep(j,0,N) };
int pos = 0;
rep(k,0,N) a.d[i][j] += d[i][k]*m.d[k][j]; for (int pw = 1 << 25; pw; pw >>= 1) {
return a; int cnt(Node* n) { return n ? n->c : 0; }
void Node::recalc() { c = cnt(l) + cnt(r) + 1; } if (pos + pw <= sz(s) && s[pos + pw-1] < sum)
} pos += pw, sum -= s[pos-1];
vector<T> operator*(const vector<T>& vec) const { }
vector<T> ret(N); template<class F> void each(Node* n, F f) {
if (n) { each(n->l, f); f(n->val); each(n->r, f); } return pos;
rep(i,0,N) rep(j,0,N) ret[i] += d[i][j] * vec[j]; }
return ret; }
};
}
M operator^(ll p) const { pair<Node*, Node*> split(Node* n, int k) {
assert(p >= 0); if (!n) return {}; FenwickTree2d.h
M a, b(*this); if (cnt(n->l) >= k) { // ”n=>val >= k” for lower bound(k) Description: Computes sums a[i,j] for all i<I, j<J, and increases single ele-
rep(i,0,N) a.d[i][i] = 1; auto pa = split(n->l, k); ments a[i,j]. Requires that the elements to be updated are known in advance
while (p) { n->l = pa.second; (call fakeUpdate() before init()).
if (p&1) a = a*b; n->recalc(); Time: O log2 N . (Use persistent segment trees for O (log N ).)
b = b*b; return {pa.first, n}; "FenwickTree.h" 157f07, 22 lines
p >>= 1; } else { struct FT2 {
} auto pa = split(n->r, k - cnt(n->l) - 1); // and j u s t ”k” vector<vi> ys; vector<FT> ft;
return a; n->r = pa.first; FT2(int limx) : ys(limx) {}
} n->recalc(); void fakeUpdate(int x, int y) {
}; return {n, pa.second}; for (; x < sz(ys); x |= x + 1) ys[x].push_back(y);
} }
} void init() {
LineContainer.h for (vi& v : ys) sort(all(v)), ft.emplace_back(sz(v));
Description: Container where you can add lines of the form kx+m, and Node* merge(Node* l, Node* r) { }
query maximum values at points x. Useful for dynamic programming (“con- if (!l) return r; int ind(int x, int y) {
vex hull trick”). if (!r) return l; return (int)(lower_bound(all(ys[x]), y) - ys[x].begin()); }
Time: O (log N ) if (l->y > r->y) {
8ec1c7, 30 lines void update(int x, int y, ll dif) {
l->r = merge(l->r, r); for (; x < sz(ys); x |= x + 1)
struct Line {
l->recalc(); ft[x].update(ind(x, y), dif);
mutable ll k, m, p;
return l; }
bool operator<(const Line& o) const { return k < o.k; }
} else { ll query(int x, int y) {
bool operator<(ll x) const { return p < x; }
r->l = merge(l, r->l); ll sum = 0;
};
r->recalc(); for (; x; x &= x - 1)
return r; sum += ft[x-1].query(ind(x-1, y));
struct LineContainer : multiset<Line, less<>> {
} return sum;
// ( for doubles , use i nf = 1/.0 , div (a , b) = a/b)
} }
static const ll inf = LLONG_MAX;
ll div(ll a, ll b) { // floored division };
Node* ins(Node* t, Node* n, int pos) {
return a / b - ((a ^ b) < 0 && a % b); }
auto pa = split(t, pos);
bool isect(iterator x, iterator y) { RMQ.h
return merge(merge(pa.first, n), pa.second);
if (y == end()) return x->p = inf, 0; Description: Range Minimum Queries on an array. Returns min(V[a], V[a
}
if (x->k == y->k) x->p = x->m > y->m ? inf : -inf; + 1], ... V[b - 1]) in constant time.
else x->p = div(y->m - x->m, x->k - y->k); Usage: RMQ rmq(values);
// Example application : move the range [ l , r ) to index k
return x->p >= y->p; rmq.query(inclusive, exclusive);
void move(Node*& t, int l, int r, int k) {
} Time: O (|V | log |V | + Q)
Node *a, *b, *c; 510c32, 16 lines
void add(ll k, ll m) {
tie(a,b) = split(t, l); tie(b,c) = split(b, r - l);
auto z = insert({k, m, 0}), y = z++, x = y; template<class T>
if (k <= l) t = merge(ins(a, b, k), c);
while (isect(y, z)) z = erase(z); struct RMQ {
else t = merge(a, ins(c, b, k - r));
if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); vector<vector<T>> jmp;
}
while ((y = x) != begin() && (--x)->p >= y->p) RMQ(const vector<T>& V) : jmp(1, V) {
KTH MoQueries Polynomial PolyRoots PolyInterpolate BerlekampMassey LinearRecurrence 5
for (int pw = 1, k = 1; pw * 2 <= sz(V); pw *= 2, ++k) {
jmp.emplace_back(sz(V) - pw * 2 + 1);
Numerical (4) }
return res;
rep(j,0,sz(jmp[k])) }
jmp[k][j] = min(jmp[k - 1][j], jmp[k - 1][j + pw]); 4.1 Polynomials and recurrences
} Polynomial.h c9b7b0, 17 lines
}
T query(int a, int b) { struct Poly { BerlekampMassey.h
vector<double> a; Description: Recovers any n-order linear recurrence relation from the first
assert(a < b); // or return i n f i f a == b
double operator()(double x) const { 2n terms of the recurrence. Useful for guessing linear recurrences after brute-
int dep = 31 - __builtin_clz(b - a);
double val = 0; forcing the first terms. Should work on any field, but numerical stability for
return min(jmp[dep][a], jmp[dep][b - (1 << dep)]);
for (int i = sz(a); i--;) (val *= x) += a[i]; floats is not guaranteed. Output will have size ≤ n.
}
return val; Usage: berlekampMassey({0, 1, 1, 3, 5, 11}) // {1, 2}
};
Time: O N 2

}
"../number-theory/ModPow.h" 96548b, 20 lines
void diff() {
MoQueries.h rep(i,1,sz(a)) a[i-1] = i*a[i]; vector<ll> berlekampMassey(vector<ll> s) {
Description: Answer interval or tree path queries by finding an approxi- int n = sz(s), L = 0, m = 0;
a.pop_back();
mate TSP through the queries, and moving from one query to the next by vector<ll> C(n), B(n), T;
}
adding/removing points at the ends. If values are on tree edges, change step C[0] = B[0] = 1;
void divroot(double x0) {
to add/remove
√ the
 edge (a, c) and remove the initial add call (but keep in). double b = a.back(), c; a.back() = 0;
Time: O N Q ll b = 1;
a12ef4, 49 lines for(int i=sz(a)-1; i--;) c = a[i], a[i] = a[i+1]*x0+b, b=c;
void add(int ind, int end) { ... } // add a [ ind ] (end = 0 or 1) a.pop_back(); rep(i,0,n) { ++m;
void del(int ind, int end) { ... } // remove a [ ind ] } ll d = s[i] % mod;
int calc() { ... } // compute current answer }; rep(j,1,L+1) d = (d + C[j] * s[i - j]) % mod;
if (!d) continue;
T = C; ll coef = d * modpow(b, mod-2) % mod;
vi mo(vector<pii> Q) { PolyRoots.h rep(j,m,n) C[j] = (C[j] - coef * B[j - m]) % mod;
int L = 0, R = 0, blk = 350; // ∼N/sqrt (Q) Description: Finds the real roots to a polynomial.
vi s(sz(Q)), res = s; if (2 * L > i) continue;
Usage: polyRoots({{2,-3,1}},-1e9,1e9) // solve xˆ2-3x+2 = 0
L = i + 1 - L; B = T; b = d; m = 0;
Time: O n2 log(1/ϵ)

#define K(x) pii(x.first/blk, x.second ^ -(x.first/blk & 1))
iota(all(s), 0); }
"Polynomial.h" b00bfe, 23 lines
sort(all(s), [&](int s, int t){ return K(Q[s]) < K(Q[t]); });
vector<double> polyRoots(Poly p, double xmin, double xmax) { C.resize(L + 1); C.erase(C.begin());
for (int qi : s) {
if (sz(p.a) == 2) { return {-p.a[0]/p.a[1]}; } for (ll& x : C) x = (mod - x) % mod;
pii q = Q[qi];
vector<double> ret; return C;
while (L > q.first) add(--L, 0);
Poly der = p; }
while (R < q.second) add(R++, 1);
der.diff();
while (L < q.first) del(L++, 0);
auto dr = polyRoots(der, xmin, xmax);
while (R > q.second) del(--R, 1);
dr.push_back(xmin-1);
res[qi] = calc();
dr.push_back(xmax+1); LinearRecurrence.h
} Description: Generates the k’th term of an n-order linear recurrence
sort(all(dr));
return res; P
rep(i,0,sz(dr)-1) { S[i] = j S[i − j − 1]tr[j], given S[0 . . . ≥ n − 1] and tr[0 . . . n − 1]. Faster
} than matrix multiplication. Useful together with Berlekamp–Massey.
double l = dr[i], h = dr[i+1];
bool sign = p(l) > 0; Usage: linearRec({0, 1}, {1, 1}, k) // k’th Fibonacci number
vi moTree(vector<array<int, 2>> Q, vector<vi>& ed, int root=0){ Time: O n2 log k

if (sign ^ (p(h) > 0)) { f4e444, 26 lines
int N = sz(ed), pos[2] = {}, blk = 350; // ∼N/sqrt (Q)
rep(it,0,60) { // while (h = l > 1e=8)
vi s(sz(Q)), res = s, I(N), L(N), R(N), in(N), par(N); typedef vector<ll> Poly;
double m = (l + h) / 2, f = p(m);
add(0, 0), in[0] = 1; ll linearRec(Poly S, Poly tr, ll k) {
if ((f <= 0) ^ sign) l = m;
auto dfs = [&](int x, int p, int dep, auto& f) -> void { int n = sz(tr);
else h = m;
par[x] = p;
}
L[x] = N; auto combine = [&](Poly a, Poly b) {
ret.push_back((l + h) / 2);
if (dep) I[x] = N++; Poly res(n * 2 + 1);
}
for (int y : ed[x]) if (y != p) f(y, x, !dep, f); rep(i,0,n+1) rep(j,0,n+1)
}
if (!dep) I[x] = N++; res[i + j] = (res[i + j] + a[i] * b[j]) % mod;
return ret;
R[x] = N; for (int i = 2 * n; i > n; --i) rep(j,0,n)
}
}; res[i - 1 - j] = (res[i - 1 - j] + res[i] * tr[j]) % mod;
dfs(root, -1, 0, dfs); res.resize(n + 1);
#define K(x) pii(I[x[0]] / blk, I[x[1]] ^ -(I[x[0]] / blk & 1)) PolyInterpolate.h return res;
iota(all(s), 0); Description: Given n points (x[i], y[i]), computes an n-1-degree polynomial };
sort(all(s), [&](int s, int t){ return K(Q[s]) < K(Q[t]); }); p that passes through them: p(x) = a[0] ∗ x0 + ... + a[n − 1] ∗ xn−1 . For
for (int qi : s) rep(end,0,2) { numerical precision, pick x[k] = c ∗ cos(k/(n − 1) ∗ π), k = 0 . . . n − 1. Poly pol(n + 1), e(pol);
Time: O n2

int &a = pos[end], b = Q[qi][end], i = 0; 08bf48, 13 lines pol[0] = e[1] = 1;
#define step(c) { if (in[c]) { del(a, end); in[a] = 0; } \
typedef vector<double> vd;
else { add(c, end); in[c] = 1; } a = c; } for (++k; k; k /= 2) {
vd interpolate(vd x, vd y, int n) {
while (!(L[b] <= L[a] && R[a] <= R[b])) if (k % 2) pol = combine(pol, e);
vd res(n), temp(n);
I[i++] = b, b = par[b]; e = combine(e, e);
rep(k,0,n-1) rep(i,k+1,n)
while (a != b) step(par[a]); }
y[i] = (y[i] - y[k]) / (x[i] - x[k]);
while (i--) step(I[i]);
double last = 0; temp[0] = 1;
if (end) res[qi] = calc(); ll res = 0;
rep(k,0,n) rep(i,0,n) {
} rep(i,0,n) res = (res + pol[i + 1] * S[i]) % mod;
res[i] += y[k] * temp[i];
return res; return res;
swap(last, temp[i]);
} }
temp[i] -= last * x[k];
KTH GoldenSectionSearch HillClimbing Integrate IntegrateAdaptive Simplex Determinant IntDeterminant 6
4.2 Optimization d rec(F& f, d a, d b, d eps, d S) { < MP(D[r][n+1] / D[r][s], B[r])) r = i;
d c = (a + b) / 2; }
GoldenSectionSearch.h d S1 = S(a, c), S2 = S(c, b), T = S1 + S2; if (r == -1) return false;
Description: Finds the argument minimizing the function f in the interval
if (abs(T - S) <= 15 * eps || b - a < 1e-10) pivot(r, s);
[a, b] assuming f is unimodal on the interval, i.e. has only one local mini-
return T + (T - S) / 15; }
mum and no local maximum. The maximum error in the result is eps. Works
return rec(f, a, c, eps / 2, S1) + rec(f, c, b, eps / 2, S2); }
equally well for maximization with a small change in the code. See Ternary-
}
Search.h in the Various chapter for a discrete version.
template<class F> T solve(vd &x) {
Usage: double func(double x) { return 4+x+.3*x*x; }
d quad(d a, d b, F f, d eps = 1e-8) { int r = 0;
double xmin = gss(-1000,1000,func);
return rec(f, a, b, eps, S(a, b)); rep(i,1,m) if (D[i][n+1] < D[r][n+1]) r = i;
Time: O (log((b − a)/ϵ)) 31d45b, 14 lines } if (D[r][n+1] < -eps) {
double gss(double a, double b, double (*f)(double)) { pivot(r, n);
double r = (sqrt(5)-1)/2, eps = 1e-7; if (!simplex(2) || D[m+1][n+1] < -eps) return -inf;
double x1 = b - r*(b-a), x2 = a + r*(b-a); Simplex.h rep(i,0,m) if (B[i] == -1) {
double f1 = f(x1), f2 = f(x2); Description: Solves a general linear maximization problem: maximize cT x int s = 0;
while (b-a > eps) subject to Ax ≤ b, x ≥ 0. Returns -inf if there is no solution, inf if there rep(j,1,n+1) ltj(D[i]);
if (f1 < f2) { //change to > to find maximum are arbitrarily good solutions, or the maximum value of cT x otherwise. The pivot(i, s);
b = x2; x2 = x1; f2 = f1; input vector is set to an optimal x (or in the unbounded case, an arbitrary }
x1 = b - r*(b-a); f1 = f(x1); solution fulfilling the constraints). Numerical stability is not guaranteed. For }
} else { better performance, define variables such that x = 0 is viable. bool ok = simplex(1); x = vd(n);
a = x1; x1 = x2; f1 = f2; Usage: vvd A = {{1,-1}, {-1,1}, {-1,-2}}; rep(i,0,m) if (B[i] < n) x[B[i]] = D[i][n+1];
x2 = a + r*(b-a); f2 = f(x2); vd b = {1,1,-4}, c = {-1,-1}, x; return ok ? D[m][n+1] : inf;
} T val = LPSolver(A, b, c).solve(x); }
return a; Time: O (N M ∗ #pivots), where a pivot may be e.g. an edge relaxation. };
} O (2n ) in the general case. aa8530, 68 lines

typedef double T; // long double , Rational , double + mod<P>... 4.3 Matrices


HillClimbing.h typedef vector<T> vd; Determinant.h
Description: Poor man’s optimization for unimodal functions.8eeeaf, typedef vector<vd> vvd; Description: Calculates determinant of a matrix. Destroys the matrix.
14 lines
typedef array<double, 2> P; Time: O N 3 bd5cec, 15 lines
const T eps = 1e-8, inf = 1/.0;
#define MP make_pair double det(vector<vector<double>>& a) {
template<class F> pair<double, P> hillClimb(P start, F f) { #define ltj(X) if(s == -1 || MP(X[j],N[j]) < MP(X[s],N[s])) s=j int n = sz(a); double res = 1;
pair<double, P> cur(f(start), start); rep(i,0,n) {
for (double jmp = 1e9; jmp > 1e-20; jmp /= 2) { struct LPSolver { int b = i;
rep(j,0,100) rep(dx,-1,2) rep(dy,-1,2) { int m, n; rep(j,i+1,n) if (fabs(a[j][i]) > fabs(a[b][i])) b = j;
P p = cur.second; vi N, B; if (i != b) swap(a[i], a[b]), res *= -1;
p[0] += dx*jmp; vvd D; res *= a[i][i];
p[1] += dy*jmp; if (res == 0) return 0;
cur = min(cur, make_pair(f(p), p)); LPSolver(const vvd& A, const vd& b, const vd& c) : rep(j,i+1,n) {
} m(sz(b)), n(sz(c)), N(n+1), B(m), D(m+2, vd(n+2)) { double v = a[j][i] / a[i][i];
} rep(i,0,m) rep(j,0,n) D[i][j] = A[i][j]; if (v != 0) rep(k,i+1,n) a[j][k] -= v * a[i][k];
return cur; rep(i,0,m) { B[i] = n+i; D[i][n] = -1; D[i][n+1] = b[i];} }
} rep(j,0,n) { N[j] = j; D[m][j] = -c[j]; } }
N[n] = -1; D[m+1][n] = 1; return res;
Integrate.h } }
Description: Simple integration of a function over an interval using Simp-
son’s rule. The error should be proportional to h4 , although in practice you void pivot(int r, int s) { IntDeterminant.h
will want to verify that the result is stable to desired precision when epsilon T *a = D[r].data(), inv = 1 / a[s]; Description: Calculates determinant using modular arithmetics. Modulos
changes. rep(i,0,m+2) if (i != r && abs(D[i][s]) > eps) { can also be removed to get a pure-integer version.
4756fc, 7 lines
T *b = D[i].data(), inv2 = b[s] * inv; Time: O N 3

template<class F> rep(j,0,n+2) b[j] -= a[j] * inv2; 3313dc, 18 lines
double quad(double a, double b, F f, const int n = 1000) { b[s] = a[s] * inv2; const ll mod = 12345;
double h = (b - a) / 2 / n, v = f(a) + f(b); } ll det(vector<vector<ll>>& a) {
rep(i,1,n*2) rep(j,0,n+2) if (j != s) D[r][j] *= inv; int n = sz(a); ll ans = 1;
v += f(a + i*h) * (i&1 ? 4 : 2); rep(i,0,m+2) if (i != r) D[i][s] *= -inv; rep(i,0,n) {
return v * h / 3; D[r][s] = inv; rep(j,i+1,n) {
} swap(B[r], N[s]); while (a[j][i] != 0) { // gcd step
} ll t = a[i][i] / a[j][i];
IntegrateAdaptive.h if (t) rep(k,i,n)
Description: Fast integration using an adaptive Simpson’s rule. bool simplex(int phase) { a[i][k] = (a[i][k] - a[j][k] * t) % mod;
Usage: double sphereVolume = quad(-1, 1, [](double x) { int x = m + phase - 1; swap(a[i], a[j]);
return quad(-1, 1, [&](double y) { for (;;) { ans *= -1;
return quad(-1, 1, [&](double z) { int s = -1; }
return x*x + y*y + z*z < 1; });});}); rep(j,0,n+1) if (N[j] != -phase) ltj(D[x]); }
92dd79, 15 lines if (D[x][s] >= -eps) return true; ans = ans * a[i][i] % mod;
typedef double d; int r = -1; if (!ans) return 0;
#define S(a,b) (f(a) + 4*f((a+b) / 2) + f(b)) * (b-a) / 6 rep(i,0,m) { }
if (D[i][s] <= eps) continue; return (ans + mod) % mod;
template <class F> if (r == -1 || MP(D[i][n+1] / D[i][s], B[i]) }
KTH SolveLinear SolveLinear2 SolveLinearBinary MatrixInverse Tridiagonal FastFourierTransform 7
SolveLinear.h if (br == n) { Tridiagonal.h
Description: Solves A ∗ x = b. If there are multiple solutions, an arbitrary rep(j,i,n) if(b[j]) return -1; Description: x = tridiagonal(d, p, q, b) solves the equation system
one is returned. Returns rank, or -1 if no solutions. Data in A and b is lost. break;
b0 d0 p0 0 0 ··· 0 x0
    
Time: O n2 m }
44c9ab, 38 lines  b1   q0 d1 p1 0 ··· 0   x1
int bc = (int)A[br]._Find_next(i-1); 
typedef vector<double> vd;
 b
2
  0 q1 d2 p2 ··· 0   x2
  
swap(A[i], A[br]); 
 b
 
 x

const double eps = 1e-12; = . . . .
  
swap(b[i], b[br]);  3
 . . .. .. .. .
 3

.

 . . . . . .

.

swap(col[i], col[bc]); 
.
 
.

int solveLinear(vector<vd>& A, vd& b, vd& x) { rep(j,0,n) if (A[j][i] != A[j][bc]) {
 .   0 0 ··· qn−3 dn−2 pn−2   . 
int n = sz(A), m = sz(x), rank = 0, br, bc; A[j].flip(i); A[j].flip(bc); bn−1 0 0 ··· 0 qn−2 dn−1 xn−1
if (n) assert(sz(A[0]) == m); }
vi col(m); iota(all(col), 0); This is useful for solving problems on the type
rep(j,i+1,n) if (A[j][i]) {
b[j] ^= b[i]; ai = bi ai−1 + ci ai+1 + di , 1 ≤ i ≤ n,
rep(i,0,n) { A[j] ^= A[i]; where a0 , an+1 , bi , ci and di are known. a can then be obtained from
double v, bv = 0; }
rep(r,i,n) rep(c,i,m) rank++; {ai } = tridiagonal({1, −1, −1, ..., −1, 1}, {0, c1 , c2 , . . . , cn },
if ((v = fabs(A[r][c])) > bv) } {b1 , b2 , . . . , bn , 0}, {a0 , d1 , d2 , . . . , dn , an+1 }).
br = r, bc = c, bv = v;
if (bv <= eps) { Fails if the solution is not unique.
x = bs();
rep(j,i,n) if (fabs(b[j]) > eps) return -1; If |di | > |pi | + |qi−1 | for all i, or |di | > |pi−1 | + |qi |, or the matrix is positive
for (int i = rank; i--;) {
break; definite, the algorithm is numerically stable and neither tr nor the check for
if (!b[i]) continue;
} diag[i] == 0 is needed.
x[col[i]] = 1;
swap(A[i], A[br]); Time: O (N )
rep(j,0,i) b[j] ^= A[j][i]; 8f9fa8, 26 lines
swap(b[i], b[br]); } typedef double T;
swap(col[i], col[bc]); return rank; // ( multiple solutions i f rank < m) vector<T> tridiagonal(vector<T> diag, const vector<T>& super,
rep(j,0,n) swap(A[j][i], A[j][bc]); } const vector<T>& sub, vector<T> b) {
bv = 1/A[i][i];
int n = sz(b); vi tr(n);
rep(j,i+1,n) {
rep(i,0,n-1) {
double fac = A[j][i] * bv; MatrixInverse.h if (abs(diag[i]) < 1e-9 * abs(super[i])) { // diag [ i ] == 0
b[j] -= fac * b[i]; Description: Invert matrix A. Returns rank; result is stored in A unless b[i+1] -= b[i] * diag[i+1] / super[i];
rep(k,i+1,m) A[j][k] -= fac*A[i][k]; singular (rank < n). Can easily be extended to prime moduli; for prime if (i+2 < n) b[i+2] -= b[i] * sub[i+1] / super[i];
} powers, repeatedly set A−1 = A−1 (2I − AA−1 ) (mod pk ) where A−1 starts diag[i+1] = sub[i]; tr[++i] = 1;
rank++; as the inverseof A mod p, and k is doubled in each step. } else {
} Time: O n3 ebfff6, 35 lines diag[i+1] -= super[i]*sub[i]/diag[i];
int matInv(vector<vector<double>>& A) { b[i+1] -= b[i]*sub[i]/diag[i];
x.assign(m, 0);
int n = sz(A); vi col(n); }
for (int i = rank; i--;) {
vector<vector<double>> tmp(n, vector<double>(n)); }
b[i] /= A[i][i];
rep(i,0,n) tmp[i][i] = 1, col[i] = i; for (int i = n; i--;) {
x[col[i]] = b[i];
if (tr[i]) {
rep(j,0,i) b[j] -= A[j][i] * b[i];
rep(i,0,n) { swap(b[i], b[i-1]);
}
diag[i-1] = diag[i];
return rank; // ( multiple solutions i f rank < m) int r = i, c = i;
rep(j,i,n) rep(k,i,n) b[i] /= super[i-1];
}
if (fabs(A[j][k]) > fabs(A[r][c])) } else {
r = j, c = k; b[i] /= diag[i];
SolveLinear2.h if (fabs(A[r][c]) < 1e-12) return i; if (i) b[i-1] -= b[i]*super[i-1];
Description: To get all uniquely determined values of x back from Solve- A[i].swap(A[r]); tmp[i].swap(tmp[r]); }
Linear, make the following changes: rep(j,0,n) }
"SolveLinear.h" 08e495, 7 lines
swap(A[j][i], A[j][c]), swap(tmp[j][i], tmp[j][c]); return b;
rep(j,0,n) if (j != i) // instead of rep( j , i +1,n) swap(col[i], col[c]); }
// . . . then at the end : double v = A[i][i];
x.assign(m, undefined); rep(j,i+1,n) { 4.4 Fourier transforms
rep(i,0,rank) { double f = A[j][i] / v;
rep(j,rank,m) if (fabs(A[i][j]) > eps) goto fail; A[j][i] = 0;
FastFourierTransform.h
Description: fft(a) computes fˆ(k) =
P
x[col[i]] = b[i] / A[i][i]; x a[x] exp(2πi · kx/N ) for all k.
rep(k,i+1,n) A[j][k] -= f*A[i][k]; N mustPbe a power of 2. Useful for convolution: conv(a, b) = c, where
fail:; } rep(k,0,n) tmp[j][k] -= f*tmp[i][k]; c[x] = a[i]b[x − i]. For convolution of complex numbers or more than two
} vectors: FFT, multiply pointwise, divide by n, reverse(start+1, end), FFT
SolveLinearBinary.h rep(j,i+1,n) A[i][j] /= v; back. Rounding is safe if ( a2i +
P P
b2i ) log2 N < 9 · 1014 (in practice 1016 ;
Description: Solves Ax = b over F2 . If there are multiple solutions, one is rep(j,0,n) tmp[i][j] /= v; higher for random inputs). Otherwise, use NTT/FFTMod.
returned arbitrarily. Returns rank, or -1 if no solutions. Destroys A and b. A[i][i] = 1; Time: O (N log N ) with N = |A| + |B| (∼1s for N = 222 )
} 00ced6, 35 lines
Time: O n2 m

fa2d7a, 34 lines typedef complex<double> C;
typedef bitset<1000> bs; for (int i = n-1; i > 0; --i) rep(j,0,i) { typedef vector<double> vd;
double v = A[j][i]; void fft(vector<C>& a) {
int solveLinear(vector<bs>& A, vi& b, bs& x, int m) { rep(k,0,n) tmp[j][k] -= v*tmp[i][k]; int n = sz(a), L = 31 - __builtin_clz(n);
int n = sz(A), rank = 0, br; } static vector<complex<long double>> R(2, 1);
assert(m <= sz(x)); static vector<C> rt(2, 1); // (^ 10% faster i f double )
vi col(m); iota(all(col), 0); rep(i,0,n) rep(j,0,n) A[col[i]][col[j]] = tmp[i][j]; for (static int k = 2; k < n; k *= 2) {
rep(i,0,n) { return n; R.resize(n); rt.resize(n);
for (br=i; br<n; ++br) if (A[br].any()) break; } auto x = polar(1.0L, acos(-1.0L) / k);
KTH FastFourierTransformMod NumberTheoreticTransform FastSubsetTransform ModularArithmetic ModInverse ModPow ModLog ModSum 8
rep(i,k,2*k) rt[i] = R[i] = i&1 ? R[i/2] * x : R[i/2]; // and 483 << 21 (same root ) . The l a s t two are > 10^9. ll x;
} typedef vector<ll> vl; Mod(ll xx) : x(xx) {}
vi rev(n); void ntt(vl &a) { Mod operator+(Mod b) { return Mod((x + b.x) % mod); }
rep(i,0,n) rev[i] = (rev[i / 2] | (i & 1) << L) / 2; int n = sz(a), L = 31 - __builtin_clz(n); Mod operator-(Mod b) { return Mod((x - b.x + mod) % mod); }
rep(i,0,n) if (i < rev[i]) swap(a[i], a[rev[i]]); static vl rt(2, 1); Mod operator*(Mod b) { return Mod((x * b.x) % mod); }
for (int k = 1; k < n; k *= 2) for (static int k = 2, s = 2; k < n; k *= 2, s++) { Mod operator/(Mod b) { return *this * invert(b); }
for (int i = 0; i < n; i += 2 * k) rep(j,0,k) { rt.resize(n); Mod invert(Mod a) {
C z = rt[j+k] * a[i+j+k]; // (25% f a s t e r i f hand=r o l l e d ) ll z[] = {1, modpow(root, mod >> s)}; ll x, y, g = euclid(a.x, mod, x, y);
a[i + j + k] = a[i + j] - z; rep(i,k,2*k) rt[i] = rt[i / 2] * z[i & 1] % mod; assert(g == 1); return Mod((x + mod) % mod);
a[i + j] += z; } }
} vi rev(n); Mod operator^(ll e) {
} rep(i,0,n) rev[i] = (rev[i / 2] | (i & 1) << L) / 2; if (!e) return Mod(1);
vd conv(const vd& a, const vd& b) { rep(i,0,n) if (i < rev[i]) swap(a[i], a[rev[i]]); Mod r = *this ^ (e / 2); r = r * r;
if (a.empty() || b.empty()) return {}; for (int k = 1; k < n; k *= 2) return e&1 ? *this * r : r;
vd res(sz(a) + sz(b) - 1); for (int i = 0; i < n; i += 2 * k) rep(j,0,k) { }
int L = 32 - __builtin_clz(sz(res)), n = 1 << L; ll z = rt[j + k] * a[i + j + k] % mod, &ai = a[i + j]; };
vector<C> in(n), out(n); a[i + j + k] = ai - z + (z > ai ? mod : 0);
copy(all(a), begin(in)); ai += (ai + z >= mod ? z - mod : z);
rep(i,0,sz(b)) in[i].imag(b[i]); }
ModInverse.h
Description: Pre-computation of modular inverses. Assumes LIM ≤ mod
fft(in); }
and that mod is a prime.
for (C& x : in) x *= x; vl conv(const vl &a, const vl &b) { 6f684f, 3 lines
rep(i,0,n) out[i] = in[-i & (n - 1)] - conj(in[i]); if (a.empty() || b.empty()) return {}; const ll mod = 1000000007, LIM = 200000;
fft(out); int s = sz(a) + sz(b) - 1, B = 32 - __builtin_clz(s), ll* inv = new ll[LIM] - 1; inv[1] = 1;
rep(i,0,sz(res)) res[i] = imag(out[i]) / (4 * n); n = 1 << B; rep(i,2,LIM) inv[i] = mod - (mod / i) * inv[mod % i] % mod;
return res; int inv = modpow(n, mod - 2);
} vl L(a), R(b), out(n);
L.resize(n), R.resize(n); ModPow.h b83e45, 8 lines

FastFourierTransformMod.h ntt(L), ntt(R); const ll mod = 1000000007; // faster i f const


Description: Higher precision FFT, can be used for convolutions modulo rep(i,0,n)
arbitrary integers as long as N log2 N · mod < 8.6 · 1014 (in practice 1016 or out[-i & (n - 1)] = (ll)L[i] * R[i] % mod * inv % mod; ll modpow(ll b, ll e) {
higher). Inputs must be in [0, mod). ntt(out); ll ans = 1;
Time: O (N log N ), where N = |A| + |B| (twice as slow as NTT or FFT) return {out.begin(), out.begin() + s}; for (; e; b = b * b % mod, e /= 2)
"FastFourierTransform.h" b82773, 22 lines
} if (e & 1) ans = ans * b % mod;
typedef vector<ll> vl; return ans;
template<int M> vl convMod(const vl &a, const vl &b) { FastSubsetTransform.h }
if (a.empty() || b.empty()) return {}; Description:
X Transform to a basis with fast convolutions of the form
vl res(sz(a) + sz(b) - 1); c[z] =
z=x⊕y
a[x] · b[y], where ⊕ is one of AND, OR, XOR. The size ModLog.h
int B=32-__builtin_clz(sz(res)), n=1<<B, cut=int(sqrt(M));
of a must be a power of two. Description: Returns the smallest x > 0 s.t. ax = b (mod m), or −1 if no
vector<C> L(n), R(n), outs(n), outl(n); such x exists.
Time: O (N log N ) 464cf3, 16 lines √ modLog(a,1,m)
 can be used to calculate the order of a.
rep(i,0,sz(a)) L[i] = C((int)a[i] / cut, (int)a[i] % cut); Time: O m c040b8, 11 lines
rep(i,0,sz(b)) R[i] = C((int)b[i] / cut, (int)b[i] % cut); void FST(vi& a, bool inv) {
fft(L), fft(R); for (int n = sz(a), step = 1; step < n; step *= 2) { ll modLog(ll a, ll b, ll m) {
rep(i,0,n) { for (int i = 0; i < n; i += 2 * step) rep(j,i,i+step) { ll n = (ll) sqrt(m) + 1, e = 1, f = 1, j = 1;
int j = -i & (n - 1); int &u = a[j], &v = a[j + step]; tie(u, v) = unordered_map<ll, ll> A;
outl[j] = (L[i] + conj(L[j])) * R[i] / (2.0 * n); inv ? pii(v - u, u) : pii(v, u + v); // AND while (j <= n && (e = f = e * a % m) != b % m)
outs[j] = (L[i] - conj(L[j])) * R[i] / (2.0 * n) / 1i; inv ? pii(v, u - v) : pii(u + v, u); // OR A[e * b % m] = j++;
} pii(u + v, u - v); // XOR if (e == b % m) return j;
fft(outl), fft(outs); } if (__gcd(m, e) == __gcd(m, b))
rep(i,0,sz(res)) { } rep(i,2,n+2) if (A.count(e = e * f % m))
ll av = ll(real(outl[i])+.5), cv = ll(imag(outs[i])+.5); if (inv) for (int& x : a) x /= sz(a); // XOR only return n * i - A[e];
ll bv = ll(imag(outl[i])+.5) + ll(real(outs[i])+.5); } return -1;
res[i] = ((av % M * cut + bv) % M * cut + cv) % M; vi conv(vi a, vi b) { }
} FST(a, 0); FST(b, 0);
return res; rep(i,0,sz(a)) a[i] *= b[i]; ModSum.h
} FST(a, 1); return a; Description: Sums of mod’ed arithmetic progressions.
Pto−1
} modsum(to, c, k, m) = i=0 (ki + c)%m. divsum is similar but for
NumberTheoreticTransform.h floored division.
Description: ntt(a) computes fˆ(k) = xk Time: log(m), with a large constant.
P
x a[x]g for all k, where g =
root(mod−1)/N . N must be a power of 2. Useful for convolution modulo spe- Number theory (5) typedef unsigned long long ull;
5c5bc5, 16 lines

cific nice primes of the form 2a b + 1, where the convolution result has size ull sumsq(ull to) { return to / 2 * ((to-1) | 1); }
at mostP 2a . For arbitrary modulo, see FFTMod. conv(a, b) = c, where
c[x] = a[i]b[x − i]. For manual convolution: NTT the inputs, multiply
5.1 Modular arithmetic
ull divsum(ull to, ull c, ull k, ull m) {
pointwise, divide by n, reverse(start+1, end), NTT back. Inputs must be in ModularArithmetic.h ull res = k / m * sumsq(to) + c / m * to;
[0, mod). Description: Operators for modular arithmetic. You need to set mod to k %= m; c %= m;
Time: O (N log N ) some number first and then you can use the structure. if (!k) return res;
"../number-theory/ModPow.h" ced03d, 35 lines "euclid.h" 35bfea, 18 lines ull to2 = (to * k + c) / m;
const ll mod = (119 << 23) + 1, root = 62; // = 998244353 const ll mod = 17; // change to something e l s e return res + (to - 1) * to2 - divsum(to2, m-1 - c, m, k);
// For p < 2^30 there i s also e . g . 5 << 25, 7 << 26, 479 << 21 struct Mod { }
KTH ModMulLL ModSqrt FastEratosthenes MillerRabin Factor euclid CRT phiFunction ContinuedFractions 9
for (int L = 1; L <= R; L += S) { CRT.h
ll modsum(ull to, ll c, ll k, ll m) { array<bool, S> block{}; Description: Chinese Remainder Theorem.
c = ((c % m) + m) % m; for (auto &[p, idx] : cp) crt(a, m, b, n) computes x such that x ≡ a (mod m), x ≡ b (mod n). If
k = ((k % m) + m) % m; for (int i=idx; i < S+L; idx = (i+=p)) block[i-L] = 1; |a| < m and |b| < n, x will obey 0 ≤ x < lcm(m, n). Assumes mn < 262 .
return to * c + k * sumsq(to) - m * divsum(to, c, k, m); rep(i,0,min(S, R - L)) Time: log(n)
} if (!block[i]) pr.push_back((L + i) * 2 + 1); "euclid.h" 04d93a, 7 lines
} ll crt(ll a, ll m, ll b, ll n) {
for (int i : pr) isPrime[i] = 1;
ModMulLL.h return pr;
if (n > m) swap(a, b), swap(m, n);
Description: Calculate a·b mod c (or ab mod c) for 0 ≤ a, b ≤ c ≤ 7.2·1018 . ll x, y, g = euclid(m, n, x, y);
} assert((a - b) % g == 0); // e l s e no solution
Time: O (1) for modmul, O (log b) for modpow bbbd8f, 11 lines
x = (b - a) % n * x % n / g * m + a;
typedef unsigned long long ull; return x < 0 ? x + m*n/g : x;
ull modmul(ull a, ull b, ull M) { MillerRabin.h }
ll ret = a * b - M * ull(1.L / M * a * b); Description: Deterministic Miller-Rabin primality test. Guaranteed to
return ret + M * (ret < 0) - M * (ret >= (ll)M); work for numbers up to 7 · 1018 ; for larger numbers, use Python and ex-
} tend A randomly. 5.3.1 Bézout’s identity
ull modpow(ull b, ull e, ull mod) { Time: 7 times the complexity of ab mod c. For a ̸=, b ̸= 0, then d = gcd(a, b) is the smallest positive integer
"ModMulLL.h" 60dcd1, 12 lines
ull ans = 1; for which there are integer solutions to
for (; e; b = modmul(b, b, mod), e /= 2) bool isPrime(ull n) {
if (e & 1) ans = modmul(ans, b, mod); if (n < 2 || n % 6 % 4 != 1) return (n | 1) == 3;
return ans; ull A[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}, ax + by = d
} s = __builtin_ctzll(n-1), d = n >> s;
for (ull a : A) { // ^ count t r a i l i n g zeroes If (x, y) is one solution, then all solutions are given by
ull p = modpow(a%n, d, n), i = s;
ModSqrt.h while (p != 1 && p != n - 1 && a % n && i--)
 
Description: Tonelli-Shanks algorithm for modular square roots. Finds x kb ka
s.t. x2 = a (mod p) (−x gives the other solution).
p = modmul(p, p, n); x+ ,y − , k∈Z
if (p != n-1 && i != s) return 0; gcd(a, b) gcd(a, b)
Time: O log2 p worst case, O (log p) for most p
}
"ModPow.h" 19a793, 24 lines
return 1;
ll sqrt(ll a, ll p) { } phiFunction.h
a %= p; if (a < 0) a += p; Description: Euler’s ϕ function is defined as ϕ(n) := # of positive integers
if (a == 0) return 0; ≤ n that are coprime with n. ϕ(1) = 1, p prime ⇒ ϕ(pk ) = (p − 1)pk−1 ,
assert(modpow(a, (p-1)/2, p) == 1); // e l s e no solution Factor.h k
m, n coprime ⇒ ϕ(mn) = ϕ(m)ϕ(n). If n = p1 1 p2 2 ...pk
k r then ϕ(n) =
if (p % 4 == 3) return modpow(a, (p+1)/4, p); r
Description: Pollard-rho randomized factorization algorithm. Returns k1 −1 kr −1
// a^(n+3)/8 or 2^(n+3)/8 * 2^(n=1)/4 works i f p % 8 == 5
Q
(p1 − 1)p1 ...(pr − 1)pr . ϕ(n) = n · p|n (1 − 1/p).
 ofa number, in arbitrary order (e.g. 2299 -> {11, 19, 11}).
prime factors P P
ll s = p - 1, n = 2; Time: O n1/4 , less for numbers with small factors. d|n ϕ(d) = n, 1≤k≤n,gcd(k,n)=1 k = nϕ(n)/2, n > 1
int r = 0, m; Euler’s thm: a, n coprime ⇒ aϕ(n) ≡ 1 (mod n).
"ModMulLL.h", "MillerRabin.h" d8d98d, 18 lines
while (s % 2 == 0)
ull pollard(ull n) { Fermat’s little thm: p prime ⇒ ap−1 ≡ 1 (mod p) ∀a.
++r, s /= 2; cf7d6d, 8 lines
while (modpow(n, (p - 1) / 2, p) != p - 1) ++n; ull x = 0, y = 0, t = 30, prd = 2, i = 1, q; const int LIM = 5000000;
ll x = modpow(a, (s + 1) / 2, p); auto f = [&](ull x) { return modmul(x, x, n) + i; }; int phi[LIM];
ll b = modpow(a, s, p), g = modpow(n, s, p); while (t++ % 40 || __gcd(prd, n) == 1) {
for (;; r = m) { if (x == y) x = ++i, y = f(x); void calculatePhi() {
ll t = b; if ((q = modmul(prd, max(x,y) - min(x,y), n))) prd = q; rep(i,0,LIM) phi[i] = i&1 ? i : i/2;
for (m = 0; m < r && t != 1; ++m) x = f(x), y = f(f(y)); for (int i = 3; i < LIM; i += 2) if(phi[i] == i)
t = t * t % p; } for (int j = i; j < LIM; j += i) phi[j] -= phi[j] / i;
if (m == 0) return x; return __gcd(prd, n); }
ll gs = modpow(g, 1LL << (r - m - 1), p); }
vector<ull> factor(ull n) {
g = gs * gs % p;
x = x * gs % p; if (n == 1) return {}; 5.4 Fractions
b = b * g % p; if (isPrime(n)) return {n}; ContinuedFractions.h
} ull x = pollard(n); Description: Given N and a real number x ≥ 0, finds the closest rational
} auto l = factor(x), r = factor(n / x); approximation p/q with p, q ≤ N . It will obey |p/q − x| ≤ 1/qN .
l.insert(l.end(), all(r)); For consecutive convergents, pk+1 qk − qk+1 pk = (−1)k . (pk /qk alternates
return l; between > x and < x.) If x is rational, y eventually becomes ∞; if x is the
5.2 Primality } root of a degree 2 polynomial the a’s eventually become cyclic.
FastEratosthenes.h Time: O (log N ) dd6c5e, 21 lines
Description: Prime sieve for generating all primes smaller than LIM.
Time: LIM=1e9 ≈ 1.5s 6b2912, 20 lines
5.3 Divisibility typedef double d; // for N ∼ 1e7 ; long double for N ∼ 1e9
pair<ll, ll> approximate(d x, ll N) {
const int LIM = 1e6; euclid.h ll LP = 0, LQ = 1, P = 1, Q = 0, inf = LLONG_MAX; d y = x;
bitset<LIM> isPrime; Description: Finds two integers x and y, such that ax + by = gcd(a, b). If for (;;) {
vi eratosthenes() { you just need gcd, use the built in gcd instead. If a and b are coprime, then ll lim = min(P ? (N-LP) / P : inf, Q ? (N-LQ) / Q : inf),
const int S = (int)round(sqrt(LIM)), R = LIM / 2; x is the inverse of a (mod b). 33ba8f, 5 lines a = (ll)floor(y), b = min(a, lim),
vi pr = {2}, sieve(S+1); pr.reserve(int(LIM/log(LIM)*1.1)); NP = b*P + LP, NQ = b*Q + LQ;
ll euclid(ll a, ll b, ll &x, ll &y) {
vector<pii> cp; if (a > b) {
if (!b) return x = 1, y = 0, a;
for (int i = 3; i <= S; i += 2) if (!sieve[i]) { // I f b > a/2, we have a semi=convergent that gives us a
ll d = euclid(b, a % b, y, x);
cp.push_back({i, i * i / 2}); // better approximation ; i f b = a/2, we *may* have one .
return y -= a/b * x, d;
for (int j = i * i; j <= S; j += 2 * i) sieve[j] = 1; // Return {P, Q} here for a more canonical approximation .
}
} return (abs(x - (d)NP / (d)NQ) < abs(x - (d)P / (d)Q)) ?
KTH FracBinarySearch IntPerm multinomial 10
make_pair(NP, NQ) : make_pair(P, Q); 5.8 Mobius Function 6.1.4 Burnside’s lemma
} 
if (abs(y = 1/(y - (d)a)) > 3*N) { 0
 n is not square free Given a group G of symmetries and a set X, the number of
return {NP, NQ}; µ(n) = 1 n has even number of prime factors elements of X up to symmetry equals
} 
LP = P; P = NP;

−1 n has odd number of prime factors 1 X g
|X |,
LQ = Q; Q = NQ; |G| g∈G
} Mobius Inversion:
}
X X where X g are the elements fixed by g (g.x = x).
g(n) = f (d) ⇔ f (n) = µ(d)g(n/d)
FracBinarySearch.h If f (n) counts “configurations” (of some sort) of length n, we can
Description: Given f and N , finds the smallest fraction p/q ∈ [0, 1] such d|n d|n
that f (p/q) is true, and p, q ≤ N . You may want to throw an exception from ignore rotational symmetry using G = Zn to get
f if it finds an exact solution, in which case N can be removed. Other useful formulas/forms:
Usage: fracBS([](Frac f) { return f.p>=3*f.q; }, 10); // {1,3} n−1
Time: O (log(N ))
1X 1X
g(n) = f (gcd(n, k)) = f (k)ϕ(n/k).
P
27ab3e, 25 lines
d|n µ(d) = [n = 1] (very useful) n n
struct Frac { ll p, q; }; P P k=0 k|n
g(n) = n|d f (d) ⇔ f (n) = n|d µ(d/n)g(d)
template<class F>
Frac fracBS(F f, ll N) { P n P n 6.2 Partitions and subsets
g(n) = 1≤m≤n f ( m ) ⇔ f (n) = 1≤m≤n µ(m)g( m )
bool dir = 1, A = 1, B = 1; 6.2.1 Partition function
Frac lo{0, 1}, hi{1, 1}; // Set hi to 1/0 to search (0 , N]
if (f(lo)) return lo; Number of ways of writing n as a sum of positive integers,
assert(f(hi)); disregarding the order of the summands.
while (A || B) { Combinatorial (6) X
ll adv = 0, step = 1; // move hi i f dir , e l s e lo p(0) = 1, p(n) = (−1)k+1 p(n − k(3k − 1)/2)
for (int si = 0; step; (step *= 2) >>= si) {
adv += step;
6.1 Permutations k∈Z\{0}
Frac mid{lo.p * adv + hi.p, lo.q * adv + hi.q}; 6.1.1 Factorial √
if (abs(mid.p) > N || mid.q > N || dir == !f(mid)) { p(n) ∼ 0.145/n · exp(2.56 n)
adv -= step; si = 2; n 123 4 5 6 7 8 9 10
} n! 1 2 6 24 120 720 5040 40320 362880 3628800 n 0 1 2 3 4 5 6 7 8 9 20 50 100
} p(n) 1 1 2 3 5 7 11 15 22 30 627 ∼2e5 ∼2e8
hi.p += lo.p * adv; n 11 12 13 14 15 16 17
hi.q += lo.q * adv; n! 4.0e7 4.8e8 6.2e9 8.7e10 1.3e12 2.1e13 3.6e14 6.2.2 Lucas’ Theorem
dir = !dir;
swap(lo, hi);
n 20 25 30 40 50 100 150 171 Let n, m be non-negative integers and p a prime. Write
n! 2e18 2e25 3e32 8e47 3e64 9e157 6e262 >DBL MAX n= pk + ... +n1 p + n0 and m = mk pk + ... + m1 p + m0 . Then
 nkQ
A = B; B = !!adv;
} n
≡ ki=0 m ni
(mod p).
return dir ? hi : lo; IntPerm.h m i
} Description: Permutation -> integer conversion. (Not order preserving.)
Integer -> permutation can use a lookup table.
6.2.3 Binomials
5.5 Pythagorean Triples Time: O (n) 044568, 6 lines
multinomial.h k + · · · + k  P
( ki )!
1 n
The Pythagorean triples are uniquely generated by int permToInt(vi& v) { Description: Computes = .
k1 , k2 , . . . , kn k1 !k2 !...kn ! a0a312, 5 lines
int use = 0, i = 0, r = 0;
2 2 2 2 ll multinomial(vi& v) {
a = k · (m − n ), b = k · (2mn), c = k · (m + n ), for(int x:v) r = r * ++i + __builtin_popcount(use & -(1<<x)),
ll c = 1, m = v.empty() ? 1 : v[0];
use |= 1 << x; // (note : minus, not ∼! )
return r; rep(i,1,sz(v)) rep(j,0,v[i]) c = c * ++m / (j+1);
with m > n > 0, k > 0, m⊥n, and either m or n even. } return c;
}
5.6 Primes 6.1.2 Cycles
p = 962592769 is such that 221 | p − 1, which may be useful. For Let gS (n) be the number of n-permutations whose cycle lengths 6.3 General purpose numbers
hashing use 970592641 (31-bit number), 31443539979727 (45-bit), all belong to the set S. Then 6.3.1 Bernoulli numbers
3006703054056749 (52-bit). There are 78498 primes less than EGF of Bernoulli numbers is B(t) = et t−1 (FFT-able).
1 000 000. ∞
!
X xn X xn B[0, . . .] = [1, − 12 , 16 , 0, − 30
1 1
, 0, 42 , . . .]
gS (n) = exp
Primitive roots exist modulo any prime power pa , except for n=0
n! n∈S
n Sums of powers:
p = 2, a > 2, and there are ϕ(ϕ(pa )) many. For p = 2, a > 2, the n m 
group Z× 1 m + 1
2a is instead isomorphic to Z2 × Z2a−2 .
X X
6.1.3 Derangements nm = Bk · (n + 1)m+1−k
m + 1 k=0 k
5.7 Estimates Permutations of a set such that none of the elements appear in i=1

their original position.


P
d|n d = O(n log log n). Euler-Maclaurin formula for infinite sums:
∞ Z ∞ ∞
The number of divisors of n is at most around 100 for n < 5e4, Bk (k−1)
 
n! X X
500 for n < 1e7, 2000 for n < 1e10, 200 000 for n < 1e19. D(n) = (n − 1)(D(n − 1) + D(n − 2)) = nD(n − 1) + (−1)n = f (i) = f (x)dx −
k!
f (m)
e i=m m k=1
KTH BellmanFord FloydWarshall TopoSort PushRelabel 11
∞ f ′ (m) f ′′′ (m) ˆ
Z
f (m) strings with n pairs of parenthesis, correctly nested. Description: Topological sorting. Given is an oriented graph. Output is an
≈ f (x)dx + − + + O(f (5) (m))
m 2 12 720 ˆ binary trees with with n + 1 leaves (0 or 2 children). ordering of vertices, such that there are edges only from left to right. If there
are cycles, the returned list will have size smaller than n – nodes reachable
6.3.2 Stirling numbers of the first kind ˆ ordered trees with n + 1 vertices. from cycles will not be returned.
Number of permutations on n items with k cycles. ˆ ways a convex polygon with n + 2 sides can be cut into Time: O (|V | + |E|) d678d8, 8 lines
triangles by connecting vertices with straight lines. vi topoSort(const vector<vi>& gr) {
c(n, k) = c(n − 1, k − 1) + (n − 1)c(n − 1, k), c(0, 0) = 1 ˆ permutations of [n] with no 3-term increasing subseq. vi indeg(sz(gr)), q;
Pn for (auto& li : gr) for (int x : li) indeg[x]++;
k
k=0 c(n, k)x = x(x + 1) . . . (x + n − 1)
rep(i,0,sz(gr)) if (indeg[i] == 0) q.push_back(i);
rep(j,0,sz(q)) for (int x : gr[q[j]])
c(8, k) = 8, 0, 5040, 13068, 13132, 6769, 1960, 322, 28, 1 Graph (7) if (--indeg[x] == 0) q.push_back(x);
return q;
c(n, 2) = 0, 0, 1, 3, 11, 50, 274, 1764, 13068, 109584, . . . }

6.3.3 Eulerian numbers 7.1 Fundamentals


BellmanFord.h 7.2 Network flow
Number of permutations π ∈ Sn in which exactly k elements are Description: Calculates shortest paths from s in a graph that might have PushRelabel.h
greater than the previous element. k j:s s.t. π(j) > π(j + 1), negative edge weights. Unreachable nodes get dist = inf; nodes reachable Description: Push-relabel using the highest label selection rule and the gap
k + 1 j:s s.t. π(j) ≥ j, k j:s s.t. π(j) > j. through negative-weight cycles get dist = -inf. Assumes V 2 max |wi | < ∼263 . heuristic. Quite fast in practice. To obtain the actual flow, look at positive
Time: O (V E) 830a8f, 23 lines values only.
 √ 
E(n, k) = (n − k)E(n − 1, k − 1) + (k + 1)E(n − 1, k) const ll inf = LLONG_MAX; Time: O V 2 E
0ae1d4, 48 lines
struct Ed { int a, b, w, s() { return a < b ? a : -a; }};
struct PushRelabel {
E(n, 0) = E(n, n − 1) = 1 struct Node { ll dist = inf; int prev = -1; };
struct Edge {
k
! int dest, back;
void bellmanFord(vector<Node>& nodes, vector<Ed>& eds, int s) {
X n+1 ll f, c;
E(n, k) = (−1)j (k + 1 − j)n nodes[s].dist = 0;
};
j=0
j sort(all(eds), [](Ed a, Ed b) { return a.s() < b.s(); });
vector<vector<Edge>> g;
vector<ll> ec;
int lim = sz(nodes) / 2 + 2; // /3+100 with shuffled vertices
6.3.4 Stirling numbers of the second kind vector<Edge*> cur;
rep(i,0,lim) for (Ed ed : eds) {
vector<vi> hs; vi H;
Partitions of n distinct elements into exactly k groups. Node cur = nodes[ed.a], &dest = nodes[ed.b];
PushRelabel(int n) : g(n), ec(n), cur(n), hs(2*n), H(n) {}
if (abs(cur.dist) == inf) continue;
ll d = cur.dist + ed.w;
S(n, k) = S(n − 1, k − 1) + kS(n − 1, k) if (d < dest.dist) {
void addEdge(int s, int t, ll cap, ll rcap=0) {
if (s == t) return;
dest.prev = ed.a;
S(n, 1) = S(n, n) = 1 g[s].push_back({t, sz(g[t]), 0, cap});
dest.dist = (i < lim-1 ? d : -inf);
g[t].push_back({s, sz(g[s])-1, 0, rcap});
}
}
k
!
1 X k−j k
}
S(n, k) = (−1) jn rep(i,0,lim) for (Ed e : eds) {
k! j=0 j if (nodes[e.a].dist == -inf)
void addFlow(Edge& e, ll f) {
Edge &back = g[e.dest][e.back];
nodes[e.b].dist = -inf;
if (!ec[e.dest] && f) hs[H[e.dest]].push_back(e.dest);
}
6.3.5 Bell numbers }
e.f += f; e.c -= f; ec[e.dest] += f;
back.f -= f; back.c += f; ec[back.dest] -= f;
Total number of partitions of n distinct elements. B(n) = }
1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, . . . . For p prime, ll calc(int s, int t) {
FloydWarshall.h int v = sz(g); H[s] = v; ec[t] = 1;
Description: Calculates all-pairs shortest path in a directed graph that
B(pm + n) ≡ mB(n) + B(n + 1) (mod p) might have negative edge weights. Input is an distance matrix m, where
vi co(2*v); co[0] = v-1;
rep(i,0,v) cur[i] = g[i].data();
m[i][j] = inf if i and j are not adjacent. As output, m[i][j] is set to the for (Edge& e : g[s]) addFlow(e, e.c);
shortest distance between i and j, inf if no path, or -inf if the path goes
6.3.6 Labeled unrooted trees through a negative-weight cycle. for (int hi = 0;;) {
# on n vertices: nn−2 Time: O N 3

531245, 12 lines while (hs[hi].empty()) if (!hi--) return -ec[s];
# on k existing trees of size ni : n1 n2 · · · nk nk−2 const ll inf = 1LL << 62; int u = hs[hi].back(); hs[hi].pop_back();
# with degrees di : (n − 2)!/((d1 − 1)! · · · (dn − 1)!) void floydWarshall(vector<vector<ll>>& m) { while (ec[u] > 0) // discharge u
int n = sz(m); if (cur[u] == g[u].data() + sz(g[u])) {
6.3.7 Catalan numbers rep(i,0,n) m[i][i] = min(m[i][i], 0LL); H[u] = 1e9;
rep(k,0,n) rep(i,0,n) rep(j,0,n) for (Edge& e : g[u]) if (e.c && H[u] > H[e.dest]+1)
! ! ! if (m[i][k] != inf && m[k][j] != inf) { H[u] = H[e.dest]+1, cur[u] = &e;
1 2n 2n 2n (2n)! auto newDist = max(m[i][k] + m[k][j], -inf); if (++co[H[u]], !--co[hi] && hi < v)
Cn = = − = m[i][j] = min(m[i][j], newDist); rep(i,0,v) if (hi < H[i] && H[i] < v)
n+1 n n n+1 (n + 1)!n! } --co[H[i]], H[i] = v + 1;
rep(k,0,n) if (m[k][k] < 0) rep(i,0,n) rep(j,0,n) hi = H[u];
2(2n + 1) X
if (m[i][k] != inf && m[k][j] != inf) m[i][j] = -inf; } else if (cur[u]->c && H[u] == H[cur[u]->dest]+1)
C0 = 1, Cn+1 = Cn , Cn+1 = Ci Cn−i addFlow(*cur[u], min(ec[u], cur[u]->c));
n+2 }
else ++cur[u];
Cn = 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, . . . }
TopoSort.h }
ˆ sub-diagonal monotone paths in an n × n grid. bool leftOfMinCut(int a) { return H[a] >= sz(g); }
KTH MinCostMaxFlow EdmondsKarp MinCut GlobalMinCut GomoryHu hopcroftKarp 12
}; } GlobalMinCut.h
} Description: Find a global minimum cut in an undirected graph, as repre-
rep(i,0,N) for(edge& e : ed[i]) totcost += e.cost * e.flow; sented by an adjacency matrix.
MinCostMaxFlow.h Time: O V 3

return {totflow, totcost/2}; 8b0e19, 21 lines
Description: Min-cost max-flow. If costs can be negative, call setpi before }
maxflow, but note that negative cost cycles are not supported. To obtain pair<int, vi> globalMinCut(vector<vi> mat) {
the actual flow, look at positive values only. // I f some costs can be negative , c a l l t h i s before maxflow : pair<int, vi> best = {INT_MAX, {}};
Time: O (F E log(V )) where F is max flow. O (V E) for setpi. 58385b, 79 lines void setpi(int s) { // ( otherwise , leave t h i s out) int n = sz(mat);
fill(all(pi), INF); pi[s] = 0; vector<vi> co(n);
#include <bits/extc++.h> int it = N, ch = 1; ll v; rep(i,0,n) co[i] = {i};
while (ch-- && it--) rep(ph,1,n) {
const ll INF = numeric_limits<ll>::max() / 4; rep(i,0,N) if (pi[i] != INF) vi w = mat[0];
for (edge& e : ed[i]) if (e.cap) size_t s = 0, t = 0;
struct MCMF { if ((v = pi[i] + e.cost) < pi[e.to]) rep(it,0,n-ph) { // O(V^2) => O(E log V) with prio . queue
struct edge { pi[e.to] = v, ch = 1; w[t] = INT_MIN;
int from, to, rev; assert(it >= 0); // negative cost cycle s = t, t = max_element(all(w)) - w.begin();
ll cap, cost, flow; } rep(i,0,n) w[i] += mat[t][i];
}; }; }
int N; best = min(best, {w[t] - mat[t][t], co[t]});
vector<vector<edge>> ed; co[s].insert(co[s].end(), all(co[t]));
vi seen; rep(i,0,n) mat[s][i] += mat[t][i];
vector<ll> dist, pi; EdmondsKarp.h rep(i,0,n) mat[i][s] = mat[s][i];
vector<edge*> par; Description: Flow algorithm with guaranteed complexity O(V E 2 ). To get mat[0][t] = INT_MIN;
edge flow values, compare capacities before and after, and take the positive }
MCMF(int N) : N(N), ed(N), seen(N), dist(N), pi(N), par(N) {} values only. return best;
482fe0, 36 lines }
void addEdge(int from, int to, ll cap, ll cost) { template<class T> T edmondsKarp(vector<unordered_map<int, T>>&
if (from == to) return; graph, int source, int sink) {
ed[from].push_back(edge{ from,to,sz(ed[to]),cap,cost,0 }); assert(source != sink);
GomoryHu.h
Description: Given a list of edges representing an undirected flow graph,
ed[to].push_back(edge{ to,from,sz(ed[from])-1,0,-cost,0 }); T flow = 0;
returns edges of the Gomory-Hu tree. The max flow between any pair of
} vi par(sz(graph)), q = par;
vertices is given by minimum edge weight along the Gomory-Hu tree path.
Time: O (V ) Flow Computations
void path(int s) { for (;;) {
"PushRelabel.h" 0418b3, 13 lines
fill(all(seen), 0); fill(all(par), -1);
fill(all(dist), INF); par[source] = 0; typedef array<ll, 3> Edge;
dist[s] = 0; ll di; int ptr = 1; vector<Edge> gomoryHu(int N, vector<Edge> ed) {
q[0] = source; vector<Edge> tree;
__gnu_pbds::priority_queue<pair<ll, int>> q; vi par(N);
vector<decltype(q)::point_iterator> its(N); rep(i,0,ptr) { rep(i,1,N) {
q.push({ 0, s }); int x = q[i]; PushRelabel D(N); // Dinic also works
for (auto e : graph[x]) { for (Edge t : ed) D.addEdge(t[0], t[1], t[2], t[2]);
while (!q.empty()) { if (par[e.first] == -1 && e.second > 0) { tree.push_back({i, par[i], D.calc(i, par[i])});
s = q.top().second; q.pop(); par[e.first] = x; rep(j,i+1,N)
seen[s] = 1; di = dist[s] + pi[s]; q[ptr++] = e.first; if (par[j] == par[i] && D.leftOfMinCut(j)) par[j] = i;
for (edge& e : ed[s]) if (!seen[e.to]) { if (e.first == sink) goto out; }
ll val = di - pi[e.to] + e.cost; } return tree;
if (e.cap - e.flow > 0 && val < dist[e.to]) { } }
dist[e.to] = val; }
par[e.to] = &e;
if (its[e.to] == q.end()) out:
return flow; 7.3 Matching
its[e.to] = q.push({ -dist[e.to], e.to }); T inc = numeric_limits<T>::max(); hopcroftKarp.h
else for (int y = sink; y != source; y = par[y]) Description: Fast bipartite matching algorithm. Graph g should be a list
q.modify(its[e.to], { -dist[e.to], e.to }); inc = min(inc, graph[par[y]][y]); of neighbors of the left partition, and btoa should be a vector full of -1’s of
} the same size as the right partition. Returns the size of the matching. btoa[i]
} flow += inc; will be the match for vertex i on the right side, or −1 if it’s not matched.
} for (int y = sink; y != source; y = par[y]) { Usage: vi √btoa(m,
 -1); hopcroftKarp(g, btoa);
rep(i,0,N) pi[i] = min(pi[i] + dist[i], INF); int p = par[y]; Time: O VE
} if ((graph[p][y] -= inc) <= 0) graph[p].erase(y); f612e4, 42 lines

graph[y][p] += inc; bool dfs(int a, int L, vector<vi>& g, vi& btoa, vi& A, vi& B) {
pair<ll, ll> maxflow(int s, int t) { } if (A[a] != L) return 0;
ll totflow = 0, totcost = 0; } A[a] = -1;
while (path(s), seen[t]) { } for (int b : g[a]) if (B[b] == L + 1) {
ll fl = INF; B[b] = 0;
for (edge* x = par[t]; x; x = par[x->from]) if (btoa[b] == -1 || dfs(btoa[b], L + 1, g, btoa, A, B))
fl = min(fl, x->cap - x->flow); return btoa[b] = a, 1;
MinCut.h }
totflow += fl; Description: After running max-flow, the left side of a min-cut from s to t return 0;
for (edge* x = par[t]; x; x = par[x->from]) { is given by all vertices reachable from s, only traversing edges with positive }
x->flow += fl; residual capacity.
ed[x->to][x->rev].flow -= fl; int hopcroftKarp(vector<vi>& g, vi& btoa) {
KTH DFSMatching MinimumVertexCover WeightedMatching GeneralMatching SCC 13
int res = 0; int res = dfsMatching(g, match);
vi A(g.size()), B(btoa.size()), cur, next; vector<bool> lfound(n, true), seen(m); int r = matInv(A = mat), M = 2*N - r, fi, fj;
for (;;) { for (int it : match) if (it != -1) lfound[it] = false; assert(r % 2 == 0);
fill(all(A), 0); vi q, cover;
fill(all(B), 0); rep(i,0,n) if (lfound[i]) q.push_back(i); if (M != N) do {
cur.clear(); while (!q.empty()) { mat.resize(M, vector<ll>(M));
for (int a : btoa) if(a != -1) A[a] = -1; int i = q.back(); q.pop_back(); rep(i,0,N) {
rep(a,0,sz(g)) if(A[a] == 0) cur.push_back(a); lfound[i] = 1; mat[i].resize(M);
for (int lay = 1;; lay++) { for (int e : g[i]) if (!seen[e] && match[e] != -1) { rep(j,N,M) {
bool islast = 0; seen[e] = true; int r = rand() % mod;
next.clear(); q.push_back(match[e]); mat[i][j] = r, mat[j][i] = (mod - r) % mod;
for (int a : cur) for (int b : g[a]) { } }
if (btoa[b] == -1) { } }
B[b] = lay; rep(i,0,n) if (!lfound[i]) cover.push_back(i); } while (matInv(A = mat) != M);
islast = 1; rep(i,0,m) if (seen[i]) cover.push_back(n+i);
} assert(sz(cover) == res); vi has(M, 1); vector<pii> ret;
else if (btoa[b] != a && !B[b]) { return cover; rep(it,0,M/2) {
B[b] = lay; } rep(i,0,M) if (has[i])
next.push_back(btoa[b]); rep(j,i+1,M) if (A[i][j] && mat[i][j]) {
} WeightedMatching.h fi = i; fj = j; goto done;
} Description: Given a weighted bipartite graph, matches every node on the } assert(0); done:
if (islast) break; left with a node on the right such that no nodes are in two matchings and the if (fj < N) ret.emplace_back(fi, fj);
if (next.empty()) return res; sum of the edge weights is minimal. Takes cost[N][M], where cost[i][j] = cost has[fi] = has[fj] = 0;
for (int a : next) A[a] = lay; for L[i] to be matched with R[j] and returns (min cost, match), where L[i] is rep(sw,0,2) {
cur.swap(next); matched with R[match[i]]. Negate costs for max cost. Requires N ≤ M . ll a = modpow(A[fi][fj], mod-2);
} Time: O N 2 M
 rep(i,0,M) if (has[i] && A[i][fj]) {
rep(a,0,sz(g)) 1e0fe9, 31 lines ll b = A[i][fj] * a % mod;
res += dfs(a, 0, g, btoa, A, B); pair<int, vi> hungarian(const vector<vi> &a) { rep(j,0,M) A[i][j] = (A[i][j] - A[fi][j] * b) % mod;
} if (a.empty()) return {0, {}}; }
} int n = sz(a) + 1, m = sz(a[0]) + 1; swap(fi,fj);
vi u(n), v(m), p(m), ans(n - 1); }
DFSMatching.h rep(i,1,n) { }
Description: Simple bipartite matching algorithm. Graph g should be a list p[0] = i; return ret;
of neighbors of the left partition, and btoa should be a vector full of -1’s of int j0 = 0; // add ”dummy” worker 0 }
the same size as the right partition. Returns the size of the matching. btoa[i] vi dist(m, INT_MAX), pre(m, -1);
will be the match for vertex i on the right side, or −1 if it’s not matched. vector<bool> done(m + 1);
do { // d i j k s t r a
7.4 DFS algorithms
Usage: vi btoa(m, -1); dfsMatching(g, btoa);
Time: O (V E) done[j0] = true; SCC.h
522b98, 22 lines int i0 = p[j0], j1, delta = INT_MAX; Description: Finds strongly connected components in a directed graph. If
bool find(int j, vector<vi>& g, vi& btoa, vi& vis) { rep(j,1,m) if (!done[j]) { vertices u, v belong to the same component, we can reach u from v and vice
if (btoa[j] == -1) return 1; auto cur = a[i0 - 1][j - 1] - u[i0] - v[j]; versa.
vis[j] = 1; int di = btoa[j]; if (cur < dist[j]) dist[j] = cur, pre[j] = j0; Usage: scc(graph, [&](vi& v) { ... }) visits all components
for (int e : g[di]) if (dist[j] < delta) delta = dist[j], j1 = j; in reverse topological order. comp[i] holds the component
if (!vis[e] && find(e, g, btoa, vis)) { } index of a node (a component only has edges to components with
btoa[e] = di; rep(j,0,m) { lower index). ncomps will contain the number of components.
return 1; if (done[j]) u[p[j]] += delta, v[j] -= delta; Time: O (E + V ) 76b5c9, 24 lines
} else dist[j] -= delta;
return 0; } vi val, comp, z, cont;
} j0 = j1; int Time, ncomps;
int dfsMatching(vector<vi>& g, vi& btoa) { } while (p[j0]); template<class G, class F> int dfs(int j, G& g, F& f) {
vi vis; while (j0) { // update alternating path int low = val[j] = ++Time, x; z.push_back(j);
rep(i,0,sz(g)) { int j1 = pre[j0]; for (auto e : g[j]) if (comp[e] < 0)
vis.assign(sz(btoa), 0); p[j0] = p[j1], j0 = j1; low = min(low, val[e] ?: dfs(e,g,f));
for (int j : g[i]) }
if (find(j, g, btoa, vis)) { } if (low == val[j]) {
btoa[j] = i; rep(j,1,m) if (p[j]) ans[p[j] - 1] = j - 1; do {
break; return {-v[0], ans}; // min cost x = z.back(); z.pop_back();
} } comp[x] = ncomps;
} cont.push_back(x);
return sz(btoa) - (int)count(all(btoa), -1); } while (x != j);
GeneralMatching.h f(cont); cont.clear();
} Description: Matching for general graphs. Fails with probability N/mod. ncomps++;
Time: O N 3 }
MinimumVertexCover.h "../numerical/MatrixInverse-mod.h" cb1912, 40 lines return val[j] = low;
Description: Finds a minimum vertex cover in a bipartite graph. The size vector<pii> generalMatching(int N, vector<pii>& ed) { }
is the same as the size of a maximum matching, and the complement is a vector<vector<ll>> mat(N, vector<ll>(N)), A; template<class G, class F> void scc(G& g, F f) {
maximum independent set. for (pii pa : ed) { int n = sz(g);
"DFSMatching.h" da4196, 20 lines int a = pa.first, b = pa.second, r = rand() % mod; val.assign(n, 0); comp.assign(n, -1);
vi cover(vector<vi>& g, int n, int m) { mat[a][b] = r, mat[b][a] = (mod - r) % mod; Time = ncomps = 0;
vi match(m, -1); } rep(i,0,n) if (comp[i] < 0) dfs(i, g, f);
KTH BiconnectedComponents 2sat EulerWalk EdgeColoring MaximalCliques 14
} int addVar() { // ( optional ) }}
gr.emplace_back(); for (int x : D) if (x < 0 || sz(ret) != nedges+1) return {};
gr.emplace_back(); return {ret.rbegin(), ret.rend()};
BiconnectedComponents.h return N++; }
Description: Finds all biconnected components in an undirected graph, and }
runs a callback for the edges in each. In a biconnected component there are
at least two distinct paths between any two nodes. Note that a node can be void either(int f, int j) {
in several components. An edge which is not in a component is a bridge, i.e.,
not part of any cycle.
f = max(2*f, -1-2*f); 7.5 Coloring
j = max(2*j, -1-2*j);
Usage: int eid = 0; ed.resize(N); gr[f].push_back(j^1); EdgeColoring.h
for each edge (a,b) { gr[j].push_back(f^1); Description: Given a simple, undirected graph with max degree D, com-
ed[a].emplace back(b, eid); } putes a (D + 1)-coloring of the edges such that no neighboring edges share
ed[b].emplace back(a, eid++); } void setValue(int x) { either(x, x); } a color. (D-coloring is NP-hard, but can be done for bipartite graphs by
bicomps([&](const vi& edgelist) {...}); repeated matchings of max-degree nodes.)
Time: O (E + V ) c6b7c7, 32 lines void atMostOne(const vi& li) { // ( optional ) Time: O (N M ) e210e2, 31 lines
vi num, st; if (sz(li) <= 1) return; vi edgeColoring(int N, vector<pii> eds) {
vector<vector<pii>> ed; int cur = ∼li[0]; vi cc(N + 1), ret(sz(eds)), fan(N), free(N), loc;
int Time; rep(i,2,sz(li)) { for (pii e : eds) ++cc[e.first], ++cc[e.second];
template<class F> int next = addVar(); int u, v, ncols = *max_element(all(cc)) + 1;
int dfs(int at, int par, F& f) { either(cur, ∼li[i]); vector<vi> adj(N, vi(ncols, -1));
int me = num[at] = ++Time, top = me; either(cur, next); for (pii e : eds) {
for (auto [y, e] : ed[at]) if (e != par) { either(∼li[i], next); tie(u, v) = e;
if (num[y]) { cur = ∼next; fan[0] = v;
top = min(top, num[y]); } loc.assign(ncols, 0);
if (num[y] < me) either(cur, ∼li[1]); int at = u, end = u, d, c = free[u], ind = 0, i = 0;
st.push_back(e); } while (d = free[v], !loc[d] && (v = adj[u][d]) != -1)
} else { loc[d] = ++ind, cc[ind] = d, fan[ind] = v;
int si = sz(st); vi val, comp, z; int time = 0; cc[loc[d]] = c;
int up = dfs(y, e, f); int dfs(int i) { for (int cd = d; at != -1; cd ^= c ^ d, at = adj[at][cd])
top = min(top, up); int low = val[i] = ++time, x; z.push_back(i); swap(adj[at][cd], adj[end = at][cd ^ c ^ d]);
if (up == me) { for(int e : gr[i]) if (!comp[e]) while (adj[fan[i]][d] != -1) {
st.push_back(e); low = min(low, val[e] ?: dfs(e)); int left = fan[i], right = fan[++i], e = cc[i];
f(vi(st.begin() + si, st.end())); if (low == val[i]) do { adj[u][e] = left;
st.resize(si); x = z.back(); z.pop_back(); adj[left][e] = u;
} comp[x] = low; adj[right][e] = -1;
else if (up < me) st.push_back(e); if (values[x>>1] == -1) free[right] = e;
else { /* e i s a bridge */ } values[x>>1] = x&1; }
} } while (x != i); adj[u][d] = fan[i];
} return val[i] = low; adj[fan[i]][d] = u;
return top; } for (int y : {fan[0], u, end})
} for (int& z = free[y] = 0; adj[y][z] != -1; z++);
bool solve() { }
template<class F> values.assign(N, -1); rep(i,0,sz(eds))
void bicomps(F f) { val.assign(2*N, 0); comp = val; for (tie(u, v) = eds[i]; adj[u][ret[i]] != v;) ++ret[i];
num.assign(sz(ed), 0); rep(i,0,2*N) if (!comp[i]) dfs(i); return ret;
rep(i,0,sz(ed)) if (!num[i]) dfs(i, -1, f); rep(i,0,N) if (comp[2*i] == comp[2*i+1]) return 0; }
} return 1;
}
};
2sat.h 7.6 Heuristics
Description: Calculates a valid assignment to boolean variables a,
b, c,... to a 2-SAT problem, so that an expression of the type EulerWalk.h MaximalCliques.h
(a||b)&&(!a||c)&&(d||!b)&&... becomes true, or reports that it is unsatis- Description: Eulerian undirected/directed path/cycle algorithm. Input Description: Runs a callback for all maximal cliques in a graph (given as a
fiable. Negated variables are represented by bit-inversions (∼x). should be a vector of (dest, global edge index), where for undirected graphs, symmetric bitset matrix; self-edges not allowed). Callback is given a bitset
Usage: TwoSat ts(number of boolean variables); forward/backward edges have the same index. Returns a list of nodes in representing
 themaximal clique.
ts.either(0, ∼3); // Var 0 is true or var 3 is false the Eulerian path/cycle with src at both start and end, or empty list if no Time: O 3n/3 , much faster for sparse graphs
ts.setValue(2); // Var 2 is true cycle/path exists. To get edge indices back, add .second to s and ret. b0d5b1, 12 lines
ts.atMostOne({0,∼1,2}); // <= 1 of vars 0, ∼1 and 2 are true Time: O (V + E) 780b64, 15 lines typedef bitset<128> B;
ts.solve(); // Returns true iff it is solvable template<class F>
ts.values[0..N-1] holds the assigned values to the vars vi eulerWalk(vector<vector<pii>>& gr, int nedges, int src=0) {
void cliques(vector<B>& eds, F f, B P = ∼B(), B X={}, B R={}) {
Time: O (N + E), where N is the number of boolean variables, and E is the int n = sz(gr);
if (!P.any()) { if (!X.any()) f(R); return; }
number of clauses. vi D(n), its(n), eu(nedges), ret, s = {src};
5f9706, 56 lines auto q = (P | X)._Find_first();
D[src]++; // to allow Euler paths , not j u s t cycles
auto cands = P & ∼eds[q];
struct TwoSat { while (!s.empty()) {
rep(i,0,sz(eds)) if (cands[i]) {
int N; int x = s.back(), y, e, &it = its[x], end = sz(gr[x]);
R[i] = 1;
vector<vi> gr; if (it == end){ ret.push_back(x); s.pop_back(); continue; }
cliques(eds, f, P & eds[i], X & eds[i], R);
vi values; // 0 = false , 1 = true tie(y, e) = gr[x][it++];
R[i] = P[i] = 0; X[i] = 1;
if (!eu[e]) {
}
TwoSat(int n = 0) : N(n), gr(2*n) {} D[x]--, D[y]++;
}
eu[e] = 1; s.push_back(y);
KTH MaximumClique MaximumIndependentSet BinaryLifting LCA CompressTree HLD 15
MaximumClique.h vector<vi> treeJump(vi& P){ rep(i,0,m) {
Description: Quickly finds a maximum clique of a graph (given as symmet- int on = 1, d = 1; int a = li[i], b = li[i+1];
ric bitset matrix; self-edges not allowed). Can be used to find a maximum while(on < sz(P)) on *= 2, d++; li.push_back(lca.lca(a, b));
independent set by finding a clique of the complement graph. vector<vi> jmp(d, P); }
Time: Runs in about 1s for n=155 and worst case random graphs (p=.90). rep(i,1,d) rep(j,0,sz(P)) sort(all(li), cmp);
Runs faster for sparse graphs. f7c0bc, 49 lines
jmp[i][j] = jmp[i-1][jmp[i-1][j]]; li.erase(unique(all(li)), li.end());
return jmp; rep(i,0,sz(li)) rev[li[i]] = i;
typedef vector<bitset<200>> vb; } vpi ret = {pii(0, li[0])};
struct Maxclique { rep(i,0,sz(li)-1) {
double limit=0.025, pk=0; int jmp(vector<vi>& tbl, int nod, int steps){ int a = li[i], b = li[i+1];
struct Vertex { int i, d=0; }; rep(i,0,sz(tbl)) ret.emplace_back(rev[lca.lca(a, b)], b);
typedef vector<Vertex> vv; if(steps&(1<<i)) nod = tbl[i][nod]; }
vb e; return nod; return ret;
vv V; } }
vector<vi> C;
vi qmax, q, S, old; int lca(vector<vi>& tbl, vi& depth, int a, int b) {
void init(vv& r) { HLD.h
if (depth[a] < depth[b]) swap(a, b); Description: Decomposes a tree into vertex disjoint heavy paths and light
for (auto& v : r) v.d = 0; a = jmp(tbl, a, depth[a] - depth[b]);
for (auto& v : r) for (auto j : r) v.d += e[v.i][j.i]; edges such that the path from any leaf to the root contains at most log(n)
if (a == b) return a; light edges. Code does additive modifications and max queries, but can
sort(all(r), [](auto a, auto b) { return a.d > b.d; }); for (int i = sz(tbl); i--;) {
int mxD = r[0].d; support commutative segtree modifications/queries on paths and subtrees.
int c = tbl[i][a], d = tbl[i][b]; Takes as input the full adjacency list. VALS EDGES being true means that
rep(i,0,sz(r)) r[i].d = min(i, mxD) + 1; if (c != d) a = c, b = d;
} values are stored in the edges, as opposed to the nodes. All values initialized
} to the segtree default.
void expand(vv& R, int lev = 1) { return tbl[0][a];  Root must be 0.
S[lev] += S[lev - 1] - old[lev]; Time: O (log N )2
} "../data-structures/LazySegmentTree.h" 03139d, 46 lines
old[lev] = S[lev - 1];
while (sz(R)) { template <bool VALS_EDGES> struct HLD {
if (sz(q) + R.back().d <= sz(qmax)) return; LCA.h int N, tim = 0;
q.push_back(R.back().i); Description: Data structure for computing lowest common ancestors in a vector<vi> adj;
vv T; tree (with 0 as root). C should be an adjacency list of the tree, either di- vi par, siz, rt, pos;
for(auto v:R) if (e[R.back().i][v.i]) T.push_back({v.i}); rected or undirected. Node *tree;
if (sz(T)) { Time: O (N log N + Q) HLD(vector<vi> adj_)
if (S[lev]++ / ++pk < limit) init(T); "../data-structures/RMQ.h" 0f62fb, 21 lines : N(sz(adj_)), adj(adj_), par(N, -1), siz(N, 1),
int j = 0, mxk = 1, mnk = max(sz(qmax) - sz(q) + 1, 1); struct LCA { rt(N),pos(N),tree(new Node(0, N)){ dfsSz(0); dfsHld(0); }
C[1].clear(), C[2].clear(); int T = 0; void dfsSz(int v) {
for (auto v : T) { vi time, path, ret; if (par[v] != -1) adj[v].erase(find(all(adj[v]), par[v]));
int k = 1; RMQ<int> rmq; for (int& u : adj[v]) {
auto f = [&](int i) { return e[v.i][i]; }; par[u] = v;
while (any_of(all(C[k]), f)) k++; LCA(vector<vi>& C) : time(sz(C)), rmq((dfs(C,0,-1), ret)) {} dfsSz(u);
if (k > mxk) mxk = k, C[mxk + 1].clear(); void dfs(vector<vi>& C, int v, int par) { siz[v] += siz[u];
if (k < mnk) T[j++].i = v.i; time[v] = T++; if (siz[u] > siz[adj[v][0]]) swap(u, adj[v][0]);
C[k].push_back(v.i); for (int y : C[v]) if (y != par) { }
} path.push_back(v), ret.push_back(time[v]); }
if (j > 0) T[j - 1].d = 0; dfs(C, y, v); void dfsHld(int v) {
rep(k,mnk,mxk + 1) for (int i : C[k]) } pos[v] = tim++;
T[j].i = i, T[j++].d = k; } for (int u : adj[v]) {
expand(T, lev + 1); rt[u] = (u == adj[v][0] ? rt[v] : u);
} else if (sz(q) > sz(qmax)) qmax = q; int lca(int a, int b) { dfsHld(u);
q.pop_back(), R.pop_back(); if (a == b) return a; }
} tie(a, b) = minmax(time[a], time[b]); }
} return path[rmq.query(a, b)]; template <class B> void process(int u, int v, B op) {
vi maxClique() { init(V), expand(V); return qmax; } } for (; rt[u] != rt[v]; v = par[rt[v]]) {
Maxclique(vb conn) : e(conn), C(sz(e)+1), S(sz(C)), old(S) { // d i s t (a , b){return depth [ a ] + depth [ b ] = 2* depth [ lca (a , b) ] ;} if (pos[rt[u]] > pos[rt[v]]) swap(u, v);
rep(i,0,sz(e)) V.push_back({i}); }; op(pos[rt[v]], pos[v] + 1);
} }
}; if (pos[u] > pos[v]) swap(u, v);
CompressTree.h op(pos[u] + VALS_EDGES, pos[v] + 1);
Description: Given a rooted tree and a subset S of nodes, compute the }
MaximumIndependentSet.h minimal subtree that contains all the nodes by adding all (at most |S| − 1)
Description: To obtain a maximum independent set of a graph, find a max void modifyPath(int u, int v, int val) {
pairwise LCA’s and compressing edges. Returns a list of (par, orig index) process(u, v, [&](int l, int r) { tree->add(l, r, val); });
clique of the complement. If the graph is bipartite, see MinimumVertex- representing a tree rooted at 0. The root points to itself.
Cover. }
Time: O (|S| log |S|) int queryPath(int u, int v) { // Modify depending on problem
"LCA.h" 9775a0, 21 lines int res = -1e9;
typedef vector<pair<int, int>> vpi; process(u, v, [&](int l, int r) {
7.7 Trees vpi compressTree(LCA& lca, const vi& subset) { res = max(res, tree->query(l, r));
BinaryLifting.h static vi rev; rev.resize(sz(lca.time)); });
Description: Calculate power of two jumps in a tree, to support fast up- vi li = subset, &T = lca.time; return res;
ward jumps and LCAs. Assumes the root node points to itself. auto cmp = [&](int a, int b) { return T[a] < T[b]; }; }
Time: construction O (N log N ), queries O (log N ) sort(all(li), cmp); int querySubtree(int v) { // modifySubtree i s similar
bfce85, 25 lines
int m = sz(li)-1; return tree->query(pos[v] + VALS_EDGES, pos[v] + siz[v]);
KTH LinkCutTree DirectedMST Point 16
} x->c[0] = top->p = 0; while (seen[u] < 0) {
}; x->fix(); if (!heap[u]) return {-1,{}};
} Edge e = heap[u]->top();
} heap[u]->delta -= e.w, pop(heap[u]);
LinkCutTree.h bool connected(int u, int v) { // are u, v in the same tree? Q[qi] = e, path[qi++] = u, seen[u] = s;
Description: Represents a forest of unrooted trees. You can add and re- Node* nu = access(&node[u])->first(); res += e.w, u = uf.find(e.a);
move edges (as long as the result is still a forest), and check whether two return nu == access(&node[v])->first(); if (seen[u] == s) {
nodes are in the same tree. } Node* cyc = 0;
Time: All operations take amortized O (log N ). 0fb462, 90 lines
void makeRoot(Node* u) { int end = qi, time = uf.time();
access(u); do cyc = merge(cyc, heap[w = path[--qi]]);
struct Node { // Splay tree . Root ’ s pp contains tree ’ s parent . u->splay(); while (uf.join(u, w));
Node *p = 0, *pp = 0, *c[2]; if(u->c[0]) { u = uf.find(u), heap[u] = cyc, seen[u] = -1;
bool flip = 0; u->c[0]->p = 0; cycs.push_front({u, time, {&Q[qi], &Q[end]}});
Node() { c[0] = c[1] = 0; fix(); } u->c[0]->flip ^= 1; }
void fix() { u->c[0]->pp = u; }
if (c[0]) c[0]->p = this; u->c[0] = 0; rep(i,0,qi) in[uf.find(Q[i].b)] = Q[i];
if (c[1]) c[1]->p = this; u->fix(); }
// (+ update sum of subtree elements etc . i f wanted) }
} } for (auto& [u,t,comp] : cycs) { // restore so l ( optional )
void pushFlip() { Node* access(Node* u) { uf.rollback(t);
if (!flip) return; u->splay(); Edge inEdge = in[u];
flip = 0; swap(c[0], c[1]); while (Node* pp = u->pp) { for (auto& e : comp) in[uf.find(e.b)] = e;
if (c[0]) c[0]->flip ^= 1; pp->splay(); u->pp = 0; in[uf.find(inEdge.b)] = inEdge;
if (c[1]) c[1]->flip ^= 1; if (pp->c[1]) { }
} pp->c[1]->p = 0; pp->c[1]->pp = pp; } rep(i,0,n) par[i] = in[i].a;
int up() { return p ? p->c[1] == this : -1; } pp->c[1] = u; pp->fix(); u = pp; return {res, par};
void rot(int i, int b) { } }
int h = i ^ b; return u;
Node *x = c[i], *y = b == 2 ? x : x->c[h], *z = b ? y : x;
if ((y->p = p)) p->c[up()] = y;
} 7.8 Math
};
c[i] = z->c[i ^ 1]; 7.8.1 Number of Spanning Trees
if (b < 2) {
x->c[h] = y->c[h ^ 1]; DirectedMST.h Create an N × N matrix mat, and for each edge a → b ∈ G, do
y->c[h ^ 1] = x; Description: Finds a minimum spanning tree/arborescence of a directed mat[a][b]--, mat[b][b]++ (and mat[b][a]--,
} graph, given a root node. If no MST exists, returns -1.
z->c[i ^ 1] = this; Time: O (E log V ) mat[a][a]++ if G is undirected). Remove the ith row and
fix(); x->fix(); y->fix(); "../data-structures/UnionFindRollback.h" 39e620, 60 lines column and take the determinant; this yields the number of
if (p) p->fix(); struct Edge { int a, b; ll w; }; directed spanning trees rooted at i (if G is undirected, remove
swap(pp, y->pp); struct Node {
} Edge key; any row/column).
void splay() { Node *l, *r;
for (pushFlip(); p; ) { ll delta; 7.8.2 Erdős–Gallai theorem
if (p->p) p->p->pushFlip(); void prop() { A simple graph with node degrees d1 ≥ · · · ≥ dn exists iff
p->pushFlip(); pushFlip(); key.w += delta;
int c1 = up(), c2 = p->up(); if (l) l->delta += delta;
d1 + · · · + dn is even and for every k = 1 . . . n,
if (c2 == -1) p->rot(c1, 2); if (r) r->delta += delta; k n
else p->p->rot(c2, c1 != c2); delta = 0; X X
} } di ≤ k(k − 1) + min(di , k).
} Edge top() { prop(); return key; } i=1 i=k+1
Node* first() { };
pushFlip(); Node *merge(Node *a, Node *b) {
return c[0] ? c[0]->first() : (splay(), this); if (!a || !b) return a ?: b;

};
} a->prop(), b->prop();
if (a->key.w > b->key.w) swap(a, b);
Geometry (8)
swap(a->l, (a->r = merge(b, a->r)));
struct LinkCut { return a; 8.1 Geometric primitives
vector<Node> node; } Point.h
LinkCut(int N) : node(N) {} void pop(Node*& a) { a->prop(); a = merge(a->l, a->r); } Description: Class to handle points in the plane. T can be e.g. double or
long long. (Avoid int.) 47ec0a, 28 lines
void link(int u, int v) { // add an edge (u, v) pair<ll, vi> dmst(int n, int r, vector<Edge>& g) {
assert(!connected(u, v)); RollbackUF uf(n); template <class T> int sgn(T x) { return (x > 0) - (x < 0); }
makeRoot(&node[u]); vector<Node*> heap(n); template<class T>
node[u].pp = &node[v]; for (Edge e : g) heap[e.b] = merge(heap[e.b], new Node{e}); struct Point {
} ll res = 0; typedef Point P;
void cut(int u, int v) { // remove an edge (u, v) vi seen(n, -1), path(n), par(n); T x, y;
Node *x = &node[u], *top = &node[v]; seen[r] = r; explicit Point(T x=0, T y=0) : x(x), y(y) {}
makeRoot(top); x->splay(); vector<Edge> Q(n), in(n, {-1,-1}), comp; bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); }
assert(top == (x->pp ?: x->c[0])); deque<tuple<int, int, vector<Edge>>> cycs; bool operator==(P p) const { return tie(x,y)==tie(p.x,p.y); }
if (x->pp) x->pp = 0; rep(s,0,n) { P operator+(P p) const { return P(x+p.x, y+p.y); }
else { int u = s, qi = 0, w; P operator-(P p) const { return P(x-p.x, y-p.y); }
KTH lineDistance SegmentDistance SegmentIntersection lineIntersection sideOf OnSegment linearTransformation Angle CircleIntersection 17
P operator*(T d) const { return P(x*d, y*d); } if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0) P dp = p1-p0, dq = q1-q0, num(dp.cross(dq), dp.dot(dq));
P operator/(T d) const { return P(x/d, y/d); } return {(a * ob - b * oa) / (ob - oa)}; return q0 + P((r-p0).cross(num), (r-p0).dot(num))/dp.dist2();
T dot(P p) const { return x*p.x + y*p.y; } set<P> s; }
T cross(P p) const { return x*p.y - y*p.x; } if (onSegment(c, d, a)) s.insert(a);
T cross(P a, P b) const { return (a-*this).cross(b-*this); } if (onSegment(c, d, b)) s.insert(b);
T dist2() const { return x*x + y*y; } if (onSegment(a, b, c)) s.insert(c); Angle.h
double dist() const { return sqrt((double)dist2()); } if (onSegment(a, b, d)) s.insert(d); Description: A class for ordering angles (as represented by int points and
// angle to x=axis in interval [= pi , pi ] return {all(s)}; a number of rotations around the origin). Useful for rotational sweeping.
double angle() const { return atan2(y, x); } } Sometimes also represents points or vectors.
P unit() const { return *this/dist(); } // makes d i s t ()=1 Usage: vector<Angle> v = {w[0], w[0].t360() ...}; // sorted
P perp() const { return P(-y, x); } // rotates +90 degrees
P normal() const { return perp().unit(); }
lineIntersection.h int j = 0; rep(i,0,n) { while (v[j] < v[i].t180()) ++j; }
Description: // sweeps j such that (j-i) represents the number of positively
// returns point rotated ’a ’ radians ccw around the origin oriented triangles with vertices at 0 and i
If a unique intersection point of the lines going through s1,e1 0f0602, 35 lines
P rotate(double a) const {
and s2,e2 exists {1, point} is returned. If no intersection point
return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); } struct Angle {
exists {0, (0,0)} is returned and if infinitely many exists {-1, e2 r
friend ostream& operator<<(ostream& os, P p) { int x, y;
(0,0)} is returned. The wrong position will be returned if P
return os << "(" << p.x << "," << p.y << ")"; }
is Point<ll> and the intersection point does not have integer e1 s2 int t;
coordinates. Products of three coordinates are used in inter- s1
}; Angle(int x, int y, int t=0) : x(x), y(y), t(t) {}
Angle operator-(Angle b) const { return {x-b.x, y-b.y, t}; }
mediate steps so watch out for overflow if using int or ll.
int half() const {
lineDistance.h Usage: auto res = lineInter(s1,e1,s2,e2);
assert(x || y);
Description: if (res.first == 1)
cout << "intersection point at " << res.second << endl; return y < 0 || (y == 0 && x < 0);
Returns the signed distance between point p and the line con-
}
taining points a and b. Positive value on left side and negative "Point.h" a01f81, 8 lines
on right as seen from a towards b. a==b gives nan. P is sup-
res Angle t90() const { return {-y, x, t + (half() && x >= 0)}; }
template<class P>
posed to be Point<T> or Point3D<T> where T is e.g. double e p pair<int, P> lineInter(P s1, P e1, P s2, P e2) {
Angle t180() const { return {-x, -y, t + half()}; }
Angle t360() const { return {x, y, t + 1}; }
or long long. It uses products in intermediate steps so watch auto d = (e1 - s1).cross(e2 - s2); };
out for overflow if using int or long long. Using Point3D will if (d == 0) // i f p a r a l l e l
always give a non-negative distance. For Point3D, call .dist s
bool operator<(Angle a, Angle b) {
return {-(s1.cross(e1, s2) == 0), P(0, 0)}; // add a . dist2 () and b . dist2 () to also compare distances
on the result of the cross product. auto p = s2.cross(e1, e2), q = s2.cross(e2, s1);
"Point.h" f6bf6b, 4 lines return make_tuple(a.t, a.half(), a.y * (ll)b.x) <
return {1, (s1 * p + e1 * q) / d}; make_tuple(b.t, b.half(), a.x * (ll)b.y);
template<class P> } }
double lineDist(const P& a, const P& b, const P& p) {
return (double)(b-a).cross(p-a)/(b-a).dist();
} sideOf.h // Given two points , t h i s calculates the smallest angle between
Description: Returns where p is as seen from s towards e. 1/0/-1 ⇔ left/on // them, i . e . , the angle that covers the defined l i n e segment .

e res p
line/right. If the optional argument eps is given 0 is returned if p is within pair<Angle, Angle> segmentAngles(Angle a, Angle b) {
SegmentDistance.h distance eps from the line. P is supposed to be Point<T> where T is e.g. if (b < a) swap(a, b);
Description: double or long long. It uses products in intermediate steps so watch out for return (b < a.t180() ?
Returns the shortest distance between point p and the line overflow if using int or long long. make_pair(a, b) : make_pair(b, a.t360()));
segment from point s to e. s Usage: bool left = sideOf(p1,p2,q)==1; }
Usage: Point<double> a, b(2,2), p(1,1); "Point.h" 3af81c, 9 lines Angle operator+(Angle a, Angle b) { // point a + vector b
bool onSegment = segDist(a,b,p) < 1e-10; Angle r(a.x + b.x, a.y + b.y, a.t);
"Point.h" 5c88f4, 6 lines
template<class P>
int sideOf(P s, P e, P p) { return sgn(s.cross(e, p)); } if (a.t180() < r) r.t--;
typedef Point<double> P; return r.t180() < a ? r.t360() : r;
double segDist(P& s, P& e, P& p) { template<class P> }
if (s==e) return (p-s).dist(); int sideOf(const P& s, const P& e, const P& p, double eps) { Angle angleDiff(Angle a, Angle b) { // angle b = angle a
auto d = (e-s).dist2(), t = min(d,max(.0,(p-s).dot(e-s))); auto a = (e-s).cross(p-s); int tu = b.t - a.t; a.t = b.t;
return ((p-s)*d-(e-s)*t).dist()/d; double l = (e-s).dist()*eps; return {a.x*b.x + a.y*b.y, a.x*b.y - a.y*b.x, tu - (b < a)};
} return (a > l) - (a < -l); }
}
SegmentIntersection.h
Description: OnSegment.h
If a unique intersection point between the line segments going
Description: Returns true iff p lies on the line segment from s to e. Use
8.2 Circles
from s1 to e1 and from s2 to e2 exists then it is returned. CircleIntersection.h
(segDist(s,e,p)<=epsilon) instead when using Point<double>.
If no intersection point exists an empty vector is returned. e1 "Point.h" c597e8, 3 lines Description: Computes the pair of points at which two circles intersect.
If infinitely many exist a vector with 2 elements is returned,
containing the endpoints of the common line segment. The e2 template<class P> bool onSegment(P s, P e, P p) { Returns false in case of no intersection.
wrong position will be returned if P is Point<ll> and the in- r1 return p.cross(s, e) == 0 && (s - p).dot(e - p) <= 0; "Point.h" 84d6d3, 11 lines

tersection point does not have integer coordinates. Products


s1 s2 } typedef Point<double> P;
of three coordinates are used in intermediate steps so watch bool circleInter(P a,P b,double r1,double r2,pair<P, P>* out) {
out for overflow if using int or long long. r p1 if (a == b) { assert(r1 != r2); return false; }
linearTransformation.h P vec = b - a;
Usage: vector<P> inter = segInter(s1,e1,s2,e2); Description:
if (sz(inter)==1) p0 res double d2 = vec.dist2(), sum = r1+r2, dif = r1-r2,
cout << "segments intersect at " << inter[0] << endl; Apply the linear transformation (translation, rotation and q0 p = (d2 + r1*r1 - r2*r2)/(d2*2), h2 = r1*r1 - p*p*d2;
"Point.h", "OnSegment.h" 9d57f2, 13 lines scaling) which takes line p0-p1 to line q0-q1 to point r. q1 if (sum*sum < d2 || dif*dif > d2) return false;
"Point.h" 03a306, 6 lines P mid = a + vec*p, per = vec.perp() * sqrt(fmax(0, h2) / d2);
template<class P> vector<P> segInter(P a, P b, P c, P d) {
auto oa = c.cross(d, a), ob = c.cross(d, b), typedef Point<double> P; *out = {mid + per, mid - per};
return true;
oc = a.cross(b, c), od = a.cross(b, d); P linearTransformation(const P& p0, const P& p1,
}
// Checks i f intersection i s single non=endpoint point . const P& q0, const P& q1, const P& r) {
KTHCircleTangents CirclePolygonIntersection circumcircle MinimumEnclosingCircle InsidePolygon PolygonArea PolygonCenter PolygonCut ConvexHull HullDiameter PointInsideHull 18
CircleTangents.h MinimumEnclosingCircle.h PolygonCut.h e
Description: Finds the external tangents of two circles, or internal if r2 is Description: Computes the minimum circle that encloses a set of points. Description:
negated. Can return 0, 1, or 2 tangents – 0 if one circle contains the other (or Time: expected O (n) Returns a vector with the vertices of a polygon with every-
overlaps it, in the internal case, or if the circles are the same); 1 if the circles "circumcircle.h" 09dd0a, 17 lines thing to the left of the line going from s to e cut away.
are tangent to each other (in which case .first = .second and the tangent line pair<P, double> mec(vector<P> ps) { Usage: vector<P> p = ...; s
is perpendicular to the line between the centers). .first and .second give the shuffle(all(ps), mt19937(time(0))); p = polygonCut(p, P(0,0), P(1,0));
tangency points at circle 1 and 2 respectively. To find the tangents of a circle P o = ps[0]; "Point.h", "lineIntersection.h" f2b7d4, 13 lines
with a point set r2 to 0. double r = 0, EPS = 1 + 1e-8; typedef Point<double> P;
"Point.h" b0153d, 13 lines rep(i,0,sz(ps)) if ((o - ps[i]).dist() > r * EPS) { vector<P> polygonCut(const vector<P>& poly, P s, P e) {
template<class P> o = ps[i], r = 0; vector<P> res;
vector<pair<P, P>> tangents(P c1, double r1, P c2, double r2) { rep(j,0,i) if ((o - ps[j]).dist() > r * EPS) { rep(i,0,sz(poly)) {
P d = c2 - c1; o = (ps[i] + ps[j]) / 2; P cur = poly[i], prev = i ? poly[i-1] : poly.back();
double dr = r1 - r2, d2 = d.dist2(), h2 = d2 - dr * dr; r = (o - ps[i]).dist(); bool side = s.cross(e, cur) < 0;
if (d2 == 0 || h2 < 0) return {}; rep(k,0,j) if ((o - ps[k]).dist() > r * EPS) { if (side != (s.cross(e, prev) < 0))
vector<pair<P, P>> out; o = ccCenter(ps[i], ps[j], ps[k]); res.push_back(lineInter(s, e, cur, prev).second);
for (double sign : {-1, 1}) { r = (o - ps[i]).dist(); if (side)
P v = (d * dr + d.perp() * sqrt(h2) * sign) / d2; } res.push_back(cur);
out.push_back({c1 + v * r1, c2 + v * r2}); } }
} } return res;
if (h2 == 0) out.pop_back(); return {o, r}; }
return out; }
}
ConvexHull.h
8.3 Polygons Description:
InsidePolygon.h Returns a vector of the points of the convex hull in counter-
CirclePolygonIntersection.h Description: Returns true if p lies within the polygon. If strict is true, it clockwise order. Points on the edge of the hull between two
Description: Returns the area of the intersection of a circle with a ccw returns false for points on the boundary. The algorithm uses products in other points are not considered part of the hull.
polygon. intermediate steps so watch out for overflow. Time: O (n log n)
"Point.h" 310954, 13 lines
Time: O (n) Usage: vector<P> v = {P{4,4}, P{1,2}, P{2,1}};
"../../content/geometry/Point.h" a1ee63, 19 lines bool in = inPolygon(v, P{3, 3}, false); typedef Point<ll> P;
typedef Point<double> P; Time: O (n) vector<P> convexHull(vector<P> pts) {
#define arg(p, q) atan2(p.cross(q), p.dot(q)) "Point.h", "OnSegment.h", "SegmentDistance.h" 2bf504, 11 lines if (sz(pts) <= 1) return pts;
double circlePoly(P c, double r, vector<P> ps) { template<class P> sort(all(pts));
auto tri = [&](P p, P q) { bool inPolygon(vector<P> &p, P a, bool strict = true) { vector<P> h(sz(pts)+1);
auto r2 = r * r / 2; int cnt = 0, n = sz(p); int s = 0, t = 0;
P d = q - p; rep(i,0,n) { for (int it = 2; it--; s = --t, reverse(all(pts)))
auto a = d.dot(p)/d.dist2(), b = (p.dist2()-r*r)/d.dist2(); P q = p[(i + 1) % n]; for (P p : pts) {
auto det = a * a - b; if (onSegment(p[i], q, a)) return !strict; while (t >= s + 2 && h[t-2].cross(h[t-1], p) <= 0) t--;
if (det <= 0) return arg(p, q) * r2; //or : i f ( segDist (p [ i ] , q , a) <= eps) return ! s t r i c t ; h[t++] = p;
auto s = max(0., -a-sqrt(det)), t = min(1., -a+sqrt(det)); cnt ^= ((a.y<p[i].y) - (a.y<q.y)) * a.cross(p[i], q) > 0; }
if (t < 0 || 1 <= s) return arg(p, q) * r2; } return {h.begin(), h.begin() + t - (t == 2 && h[0] == h[1])};
P u = p + d * s, v = p + d * t; return cnt; }
return arg(p,u) * r2 + u.cross(v)/2 + arg(v,q) * r2; }
}; HullDiameter.h
auto sum = 0.0; PolygonArea.h Description: Returns the two points with max distance on a convex hull
rep(i,0,sz(ps)) Description: Returns twice the signed area of a polygon. Clockwise enu- (ccw, no duplicate/collinear points).
sum += tri(ps[i] - c, ps[(i + 1) % sz(ps)] - c); meration gives negative area. Watch out for overflow if using int as T! Time: O (n)
return sum; "Point.h" f12300, 6 lines "Point.h" c571b8, 12 lines
} typedef Point<ll> P;
template<class T>
T polygonArea2(vector<Point<T>>& v) { array<P, 2> hullDiameter(vector<P> S) {
T a = v.back().cross(v[0]); int n = sz(S), j = n < 2 ? 0 : 1;
pair<ll, array<P, 2>> res({0, {S[0], S[0]}});
circumcircle.h rep(i,0,sz(v)-1) a += v[i].cross(v[i+1]);
rep(i,0,j)
Description: return a;
for (;; j = (j + 1) % n) {
The circumcirle of a triangle is the circle intersecting all B }
res = max(res, {(S[i] - S[j]).dist2(), {S[i], S[j]}});
three vertices. ccRadius returns the radius of the circle going r c if ((S[(j + 1) % n] - S[j]).cross(S[i + 1] - S[i]) >= 0)
through points A, B and C and ccCenter returns the center C PolygonCenter.h break;
of the same circle. A Description: Returns the center of mass for a polygon.
}
Time: O (n)
"Point.h" 1caa3a, 9 lines return res.second;
"Point.h" 9706dc, 9 lines
typedef Point<double> P; }
typedef Point<double> P;
double ccRadius(const P& A, const P& B, const P& C) {
P polygonCenter(const vector<P>& v) {
return (B-A).dist()*(C-B).dist()*(A-C).dist()/
P res(0, 0); double A = 0; PointInsideHull.h
abs((B-A).cross(C-A))/2; Description: Determine whether a point t lies inside a convex hull (CCW
for (int i = 0, j = sz(v) - 1; i < sz(v); j = i++) {
} order, with no collinear points). Returns true if point lies within the hull. If
res = res + (v[i] + v[j]) * v[j].cross(v[i]);
P ccCenter(const P& A, const P& B, const P& C) { strict is true, points on the boundary aren’t included.
A += v[j].cross(v[i]);
P b = C-A, c = B-A; Time: O (log N )
}
return A + (b*c.dist2()-c*b.dist2()).perp()/b.cross(c)/2; "Point.h", "sideOf.h", "OnSegment.h" 71446b, 14 lines
return res / A / 3;
}
} typedef Point<ll> P;
KTH LineHullIntersection ClosestPair kdTree FastDelaunay 19
8.4 Misc. Point Set Problems // i f (p == node=>pt ) return {INF, P()};
bool inHull(const vector<P>& l, P p, bool strict = true) { return make_pair((p - node->pt).dist2(), node->pt);
int a = 1, b = sz(l) - 1, r = !strict;
ClosestPair.h }
Description: Finds the closest pair of points.
if (sz(l) < 3) return r && onSegment(l[0], l.back(), p);
Time: O (n log n)
if (sideOf(l[0], l[a], l[b]) > 0) swap(a, b); Node *f = node->first, *s = node->second;
"Point.h" ac41a6, 17 lines
if (sideOf(l[0], l[a], p) >= r || sideOf(l[0], l[b], p)<= -r) T bfirst = f->distance(p), bsec = s->distance(p);
return false; typedef Point<ll> P; if (bfirst > bsec) swap(bsec, bfirst), swap(f, s);
while (abs(a - b) > 1) { pair<P, P> closest(vector<P> v) {
int c = (a + b) / 2; assert(sz(v) > 1); // search c l o s e s t side f i r s t , other side i f needed
(sideOf(l[0], l[c], p) > 0 ? b : a) = c; set<P> S; auto best = search(f, p);
} sort(all(v), [](P a, P b) { return a.y < b.y; }); if (bsec < best.first)
return sgn(l[a].cross(l[b], p)) < r; pair<ll, pair<P, P>> ret{LLONG_MAX, {P(), P()}}; best = min(best, search(s, p));
} int j = 0; return best;
for (P p : v) { }
P d{1 + (ll)sqrt(ret.first), 0};
while (v[j].y <= p.y - d.x) S.erase(v[j++]); // find nearest point to a point , and i t s squared distance
auto lo = S.lower_bound(p - d), hi = S.upper_bound(p + d); // ( requires an arbitrary operator< for Point)
for (; lo != hi; ++lo) pair<T, P> nearest(const P& p) {
ret = min(ret, {(*lo - p).dist2(), {*lo, p}}); return search(root, p);
LineHullIntersection.h S.insert(p); }
Description: Line-convex polygon intersection. The polygon must be ccw } };
and have no collinear points. lineHull(line, poly) returns a pair describing return ret.second;
the intersection of a line with the polygon: ˆ (−1, −1) if no collision, ˆ (i, −1) }
if touching the corner i, ˆ (i, i) if along side (i, i + 1), ˆ (i, j) if crossing sides
FastDelaunay.h
Description: Fast Delaunay triangulation. Each circumcircle contains none
(i, i + 1) and (j, j + 1). In the last case, if a corner i is crossed, this is treated
as happening on side (i, i + 1). The points are returned in the same order as
kdTree.h of the input points. There must be no duplicate points. If all points are on a
Description: KD-tree (2d, can be extended to 3d) line, no triangles will be returned. Should work for doubles as well, though
the line hits the polygon. extrVertex returns the point of a hull with the
"Point.h" bac5b0, 63 lines there may be precision issues in ’circ’. Returns triangles in order {t[0][0],
max projection onto a line.
typedef long long T; t[0][1], t[0][2], t[1][0], . . . }, all counter-clockwise.
Time: O (log n)
typedef Point<T> P; Time: O (n log n)
"Point.h" 7cf45b, 39 lines
const T INF = numeric_limits<T>::max(); "Point.h" eefdf5, 88 lines
#define cmp(i,j) sgn(dir.perp().cross(poly[(i)%n]-poly[(j)%n]))
typedef Point<ll> P;
#define extr(i) cmp(i + 1, i) >= 0 && cmp(i, i - 1 + n) < 0
bool on_x(const P& a, const P& b) { return a.x < b.x; } typedef struct Quad* Q;
template <class P> int extrVertex(vector<P>& poly, P dir) {
bool on_y(const P& a, const P& b) { return a.y < b.y; } typedef __int128_t lll; // (can be l l i f coords are < 2e4)
int n = sz(poly), lo = 0, hi = n;
P arb(LLONG_MAX,LLONG_MAX); // not equal to any other point
if (extr(0)) return 0;
struct Node {
while (lo + 1 < hi) {
P pt; // i f t h i s i s a leaf , the single point in i t struct Quad {
int m = (lo + hi) / 2;
T x0 = INF, x1 = -INF, y0 = INF, y1 = -INF; // bounds Q rot, o; P p = arb; bool mark;
if (extr(m)) return m;
Node *first = 0, *second = 0; P& F() { return r()->p; }
int ls = cmp(lo + 1, lo), ms = cmp(m + 1, m);
Q& r() { return rot->rot; }
(ls < ms || (ls == ms && ls == cmp(lo, m)) ? hi : lo) = m;
T distance(const P& p) { // min squared distance to a point Q prev() { return rot->o->rot; }
}
T x = (p.x < x0 ? x0 : p.x > x1 ? x1 : p.x); Q next() { return r()->prev(); }
return lo;
T y = (p.y < y0 ? y0 : p.y > y1 ? y1 : p.y); } *H;
}
return (P(x,y) - p).dist2();
} bool circ(P p, P a, P b, P c) { // i s p in the circumcircle?
#define cmpL(i) sgn(a.cross(poly[i], b))
lll p2 = p.dist2(), A = a.dist2()-p2,
template <class P>
Node(vector<P>&& vp) : pt(vp[0]) { B = b.dist2()-p2, C = c.dist2()-p2;
array<int, 2> lineHull(P a, P b, vector<P>& poly) {
for (P p : vp) { return p.cross(a,b)*C + p.cross(b,c)*A + p.cross(c,a)*B > 0;
int endA = extrVertex(poly, (a - b).perp());
x0 = min(x0, p.x); x1 = max(x1, p.x); }
int endB = extrVertex(poly, (b - a).perp());
y0 = min(y0, p.y); y1 = max(y1, p.y); Q makeEdge(P orig, P dest) {
if (cmpL(endA) < 0 || cmpL(endB) > 0)
} Q r = H ? H : new Quad{new Quad{new Quad{new Quad{0}}}};
return {-1, -1};
if (vp.size() > 1) { H = r->o; r->r()->r() = r;
array<int, 2> res;
// s p l i t on x i f width >= height (not ideal . . . ) rep(i,0,4) r = r->rot, r->p = arb, r->o = i & 1 ? r : r->r();
rep(i,0,2) {
sort(all(vp), x1 - x0 >= y1 - y0 ? on_x : on_y); r->p = orig; r->F() = dest;
int lo = endB, hi = endA, n = sz(poly);
// divide by taking h a l f the array for each child (not return r;
while ((lo + 1) % n != hi) {
// best performance with many duplicates in the middle) }
int m = ((lo + hi + (lo < hi ? 0 : n)) / 2) % n;
int half = sz(vp)/2; void splice(Q a, Q b) {
(cmpL(m) == cmpL(endB) ? lo : hi) = m;
first = new Node({vp.begin(), vp.begin() + half}); swap(a->o->rot->o, b->o->rot->o); swap(a->o, b->o);
}
second = new Node({vp.begin() + half, vp.end()}); }
res[i] = (lo + !cmpL(hi)) % n;
} Q connect(Q a, Q b) {
swap(endA, endB);
} Q q = makeEdge(a->F(), b->p);
}
}; splice(q, a->next());
if (res[0] == res[1]) return {res[0], -1};
splice(q->r(), b);
if (!cmpL(res[0]) && !cmpL(res[1]))
struct KDTree { return q;
switch ((res[0] - res[1] + sz(poly) + 1) % sz(poly)) {
Node* root; }
case 0: return {res[0], res[0]};
KDTree(const vector<P>& vp) : root(new Node({all(vp)})) {}
case 2: return {res[1], res[1]};
pair<Q,Q> rec(const vector<P>& s) {
}
pair<T, P> search(Node *node, const P& p) { if (sz(s) <= 3) {
return res;
if (!node->first) { Q a = makeEdge(s[0], s[1]), b = makeEdge(s[1], s.back());
}
// uncomment i f we should not find the point i t s e l f : if (sz(s) == 2) return { a, a->r() };
KTH PolyhedronVolume Point3D 3dHull sphericalDistance KMP Zfunc 20
splice(a->r(), b); T x, y, z; E(b,c).rem(f.a);
auto side = s[0].cross(s[1], s[2]); explicit Point3D(T x=0, T y=0, T z=0) : x(x), y(y), z(z) {} swap(FS[j--], FS.back());
Q c = side ? connect(b, a) : 0; bool operator<(R p) const { FS.pop_back();
return {side < 0 ? c->r() : a, side < 0 ? c : b->r() }; return tie(x, y, z) < tie(p.x, p.y, p.z); } }
} bool operator==(R p) const { }
return tie(x, y, z) == tie(p.x, p.y, p.z); } int nw = sz(FS);
#define H(e) e->F(), e->p P operator+(R p) const { return P(x+p.x, y+p.y, z+p.z); } rep(j,0,nw) {
#define valid(e) (e->F().cross(H(base)) > 0) P operator-(R p) const { return P(x-p.x, y-p.y, z-p.z); } F f = FS[j];
Q A, B, ra, rb; P operator*(T d) const { return P(x*d, y*d, z*d); } #define C(a, b, c) if (E(a,b).cnt() != 2) mf(f.a, f.b, i, f.c);
int half = sz(s) / 2; P operator/(T d) const { return P(x/d, y/d, z/d); } C(a, b, c); C(a, c, b); C(b, c, a);
tie(ra, A) = rec({all(s) - half}); T dot(R p) const { return x*p.x + y*p.y + z*p.z; } }
tie(B, rb) = rec({sz(s) - half + all(s)}); P cross(R p) const { }
while ((B->p.cross(H(A)) < 0 && (A = A->next())) || return P(y*p.z - z*p.y, z*p.x - x*p.z, x*p.y - y*p.x); for (F& it : FS) if ((A[it.b] - A[it.a]).cross(
(A->p.cross(H(B)) > 0 && (B = B->r()->o))); } A[it.c] - A[it.a]).dot(it.q) <= 0) swap(it.c, it.b);
Q base = connect(B->r(), A); T dist2() const { return x*x + y*y + z*z; } return FS;
if (A->p == ra->p) ra = base->r(); double dist() const { return sqrt((double)dist2()); } };
if (B->p == rb->p) rb = base; //Azimuthal angle ( longitude ) to x=axis in interval [= pi , pi ]
double phi() const { return atan2(y, x); }
#define DEL(e, init, dir) Q e = init->dir; if (valid(e)) \ //Zenith angle ( l a t i t u d e ) to the z=axis in interval [0 , pi ]
sphericalDistance.h
Description: Returns the shortest distance on the sphere with radius ra-
while (circ(e->dir->F(), H(base), e->F())) { \ double theta() const { return atan2(sqrt(x*x+y*y),z); }
dius between the points with azimuthal angles (longitude) f1 (ϕ1 ) and f2 (ϕ2 )
Q t = e->dir; \ P unit() const { return *this/(T)dist(); } //makes d i s t ()=1
from x axis and zenith angles (latitude) t1 (θ1 ) and t2 (θ2 ) from z axis (0 =
splice(e, e->prev()); \ //returns unit vector normal to * t h i s and p
north pole). All angles measured in radians. The algorithm starts by con-
splice(e->r(), e->r()->prev()); \ P normal(P p) const { return cross(p).unit(); }
verting the spherical coordinates to cartesian coordinates so if that is what
e->o = H; H = e; e = t; \ //returns point rotated ’ angle ’ radians ccw around axis
you have you can use only the two last rows. dx*radius is then the difference
} P rotate(double angle, P axis) const {
between the two points in the x direction and d*radius is the total distance
for (;;) { double s = sin(angle), c = cos(angle); P u = axis.unit();
between the points. 611f07, 8 lines
DEL(LC, base->r(), o); DEL(RC, base, prev()); return u*dot(u)*(1-c) + (*this)*c - cross(u)*s;
if (!valid(LC) && !valid(RC)) break; } double sphericalDistance(double f1, double t1,
if (!valid(LC) || (valid(RC) && circ(H(RC), H(LC)))) }; double f2, double t2, double radius) {
base = connect(RC, base->r()); double dx = sin(t2)*cos(f2) - sin(t1)*cos(f1);
else 3dHull.h double dy = sin(t2)*sin(f2) - sin(t1)*sin(f1);
base = connect(base->r(), LC->r()); Description: Computes all faces of the 3-dimension hull of a point set. *No double dz = cos(t2) - cos(t1);
} four points must be coplanar*, or else random results will be returned. All double d = sqrt(dx*dx + dy*dy + dz*dz);
return { ra, rb }; faces will point return radius*2*asin(d/2);
}  outwards.
Time: O n2 }
"Point3D.h" 5b45fc, 49 lines
vector<P> triangulate(vector<P> pts) {
typedef Point3D<double> P3;
sort(all(pts)); assert(unique(all(pts)) == pts.end());
if (sz(pts) < 2) return {};
Strings (9)
Q e = rec(pts).first; struct PR {
vector<Q> q = {e}; void ins(int x) { (a == -1 ? a : b) = x; } KMP.h
int qi = 0; void rem(int x) { (a == x ? a : b) = -1; } Description: pi[x] computes the length of the longest prefix of s that ends
while (e->o->F().cross(e->F(), e->p) < 0) e = e->o; int cnt() { return (a != -1) + (b != -1); } at x, other than s[0...x] itself (abacaba -> 0010123). Can be used to find all
#define ADD { Q c = e; do { c->mark = 1; pts.push_back(c->p); \ int a, b; occurrences of a string.
q.push_back(c->r()); c = c->next(); } while (c != e); } }; Time: O (n) d4375c, 16 lines
ADD; pts.clear();
struct F { P3 q; int a, b, c; }; vi pi(const string& s) {
while (qi < sz(q)) if (!(e = q[qi++])->mark) ADD;
vi p(sz(s));
return pts;
vector<F> hull3d(const vector<P3>& A) { rep(i,1,sz(s)) {
}
assert(sz(A) >= 4); int g = p[i-1];
vector<vector<PR>> E(sz(A), vector<PR>(sz(A), {-1, -1})); while (g && s[i] != s[g]) g = p[g-1];
8.5 3D #define E(x,y) E[f.x][f.y] p[i] = g + (s[i] == s[g]);
vector<F> FS; }
PolyhedronVolume.h return p;
Description: Magic formula for the volume of a polyhedron. Faces should auto mf = [&](int i, int j, int k, int l) {
P3 q = (A[j] - A[i]).cross((A[k] - A[i])); }
point outwards. 3058c3, 6 lines if (q.dot(A[l]) > q.dot(A[i]))
template<class V, class L> q = q * -1; vi match(const string& s, const string& pat) {
double signedPolyVolume(const V& p, const L& trilist) { F f{q, i, j, k}; vi p = pi(pat + ’\0’ + s), res;
double v = 0; E(a,b).ins(k); E(a,c).ins(j); E(b,c).ins(i); rep(i,sz(p)-sz(s),sz(p))
for (auto i : trilist) v += p[i.a].cross(p[i.b]).dot(p[i.c]); FS.push_back(f); if (p[i] == sz(pat)) res.push_back(i - 2 * sz(pat));
return v / 6; }; return res;
} rep(i,0,4) rep(j,i+1,4) rep(k,j+1,4) }
mf(i, j, k, 6 - i - j - k);
Point3D.h rep(i,4,sz(A)) {
Zfunc.h
Description: Class to handle points in 3D space. T can be e.g. double or Description: z[i] computes the length of the longest common prefix of s[i:]
long long. rep(j,0,sz(FS)) { and s, except z[0] = 0. (abacaba -> 0010301)
8058ae, 32 lines F f = FS[j]; Time: O (n) ee09e2, 12 lines
template<class T> struct Point3D { if(f.q.dot(A[i]) > f.q.dot(A[f.a])) {
typedef Point3D P; E(a,b).rem(f.c); vi Z(const string& S) {
typedef const P& R; E(a,c).rem(f.b); vi z(sz(S));
KTH Manacher MinRotation SuffixArray SuffixTree Hashing AhoCorasick 21
int l = -1, r = -1; } Hashing.h
rep(i,1,sz(S)) { for (int i = 0, j; i < n - 1; lcp[x[i++]] = k) Description: Self-explanatory methods for string hashing. 2d2a67, 44 lines
z[i] = i >= r ? 0 : min(r - i, z[i - l]); for (k && k--, j = sa[x[i] - 1];
while (i + z[i] < sz(S) && S[i + z[i]] == S[z[i]]) s[i + k] == s[j + k]; k++); // Arithmetic mod 2^64=1. 2x slower than mod 2^64 and more
z[i]++; } // code , but works on e v i l t e s t data (e . g . Thue=Morse, where
if (i + z[i] > r) }; // ABBA. . . and BAAB. . . of length 2^10 hash the same mod 2^64) .
l = i, r = i + z[i]; // ”typedef u l l H;” instead i f you think t e s t data i s random,
} // or work mod 10^9+7 i f the Birthday paradox i s not a problem .
return z; typedef uint64_t ull;
} struct H {
ull x; H(ull x=0) : x(x) {}
SuffixTree.h H operator+(H o) { return x + o.x + (x + o.x < x); }
Manacher.h Description: Ukkonen’s algorithm for online suffix tree construction. Each H operator-(H o) { return *this + ∼o.x; }
Description: For each position in a string, computes p[0][i] = half length node contains indices [l, r) into the string, and a list of child nodes. Suffixes H operator*(H o) { auto m = (__uint128_t)x * o.x;
of longest even palindrome around pos i, p[1][i] = longest odd (half rounded are given by traversals of this tree, joining [l, r) substrings. The root is 0 (has return H((ull)m) + (ull)(m >> 64); }
down). l = -1, r = 0), non-existent children are -1. To get a complete tree, append ull get() const { return x + !∼x; }
Time: O (N ) a dummy symbol – otherwise it may contain an incomplete path (still useful bool operator==(H o) const { return get() == o.get(); }
e7ad79, 13 lines
for substring matching, though). bool operator<(H o) const { return get() < o.get(); }
array<vi, 2> manacher(const string& s) { Time: O (26N ) };
aae0b8, 50 lines
int n = sz(s); static const H C = (ll)1e11+3; // (order ∼ 3e9 ; random also ok)
array<vi,2> p = {vi(n+1), vi(n)}; struct SuffixTree {
rep(z,0,2) for (int i=0,l=0,r=0; i < n; i++) { enum { N = 200010, ALPHA = 26 }; // N ∼ 2*maxlen+10
int toi(char c) { return c - ’a’; } struct HashInterval {
int t = r-i+!z; vector<H> ha, pw;
if (i<r) p[z][i] = min(t, p[z][l+t]); string a; // v = cur node , q = cur position
int t[N][ALPHA],l[N],r[N],p[N],s[N],v=0,q=0,m=2; HashInterval(string& str) : ha(sz(str)+1), pw(ha) {
int L = i-p[z][i], R = i+p[z][i]-!z; pw[0] = 1;
while (L>=1 && R+1<n && s[L-1] == s[R+1]) rep(i,0,sz(str))
p[z][i]++, L--, R++; void ukkadd(int i, int c) { suff:
if (r[v]<=q) { ha[i+1] = ha[i] * C + str[i],
if (R>r) l=L, r=R; pw[i+1] = pw[i] * C;
} if (t[v][c]==-1) { t[v][c]=m; l[m]=i;
p[m++]=v; v=s[v]; q=r[v]; goto suff; } }
return p; H hashInterval(int a, int b) { // hash [ a , b)
} v=t[v][c]; q=l[v];
} return ha[b] - ha[a] * pw[b - a];
if (q==-1 || c==toi(a[q])) q++; else { }
MinRotation.h l[m+1]=i; p[m+1]=m; l[m]=l[v]; r[m]=q; };
Description: Finds the lexicographically smallest rotation of a string. p[m]=p[v]; t[m][c]=m+1; t[m][toi(a[q])]=v;
Usage: rotate(v.begin(), v.begin()+minRotation(v), v.end()); l[v]=q; p[v]=m; t[p[m]][toi(a[l[m]])]=m; vector<H> getHashes(string& str, int length) {
Time: O (N ) v=s[p[m]]; q=l[m]; if (sz(str) < length) return {};
d07a42, 8 lines
while (q<r[m]) { v=t[v][toi(a[q])]; q+=r[v]-l[v]; } H h = 0, pw = 1;
int minRotation(string s) { rep(i,0,length)
int a=0, N=sz(s); s += s; if (q==r[m]) s[m]=v; else s[m]=m+2;
q=r[v]-(q-r[m]); m+=2; goto suff; h = h * C + str[i], pw = pw * C;
rep(b,0,N) rep(k,0,N) { vector<H> ret = {h};
if (a+k == b || s[a+k] < s[b+k]) {b += max(0, k-1); break;} }
} rep(i,length,sz(str)) {
if (s[a+k] > s[b+k]) { a = b; break; } ret.push_back(h = h * C + str[i] - pw * str[i-length]);
} }
return a; SuffixTree(string a) : a(a) {
fill(r,r+N,sz(a)); return ret;
} }
memset(s, 0, sizeof s);
memset(t, -1, sizeof t);
SuffixArray.h fill(t[1],t[1]+ALPHA,0); H hashString(string& s){H h{}; for(char c:s) h=h*C+c;return h;}
Description: Builds suffix array for a string. sa[i] is the starting index s[0] = 1; l[0] = l[1] = -1; r[0] = r[1] = p[0] = p[1] = 0;
of the suffix which is i’th in the sorted suffix array. The returned vector rep(i,0,sz(a)) ukkadd(i, toi(a[i]));
is of size n + 1, and sa[0] = n. The lcp array contains longest common } AhoCorasick.h
prefixes for neighbouring strings in the suffix array: lcp[i] = lcp(sa[i], Description: Aho-Corasick automaton, used for multiple pattern matching.
sa[i-1]), lcp[0] = 0. The input string must not contain any zero bytes. // example : find longest common substring ( uses ALPHA = 28) Initialize with AhoCorasick ac(patterns); the automaton start node will be
Time: O (n log n) pii best; at index 0. find(word) returns for each position the index of the longest word

bc716b, 22 lines
int lcs(int node, int i1, int i2, int olen) { that ends there, or -1 if none. findAll(−, word) finds all words (up to N N
struct SuffixArray { many if no duplicate patterns) that start at each position (shortest first).
if (l[node] <= i1 && i1 < r[node]) return 1;
vi sa, lcp; Duplicate patterns are allowed; empty patterns are not. To find the longest
if (l[node] <= i2 && i2 < r[node]) return 2;
SuffixArray(string& s, int lim=256) { // or basic string<int> words that start at each position, reverse all input. For large alphabets, split
int mask = 0, len = node ? olen + (r[node] - l[node]) : 0;
int n = sz(s) + 1, k = 0, a, b; each symbol into chunks, with sentinel bits for symbol boundaries.
rep(c,0,ALPHA) if (t[node][c] != -1)
vi x(all(s)), y(n), ws(max(n, lim)); Time: construction takes O (26N ), where N = sum of length of patterns.
mask |= lcs(t[node][c], i1, i2, len);
x.push_back(0), sa = lcp = y, iota(all(sa), 0); find(x) is O (N ), where N = length of x. findAll is O (N M ). f35677, 66 lines
if (mask == 3)
for (int j = 0, p = 0; p < n; j = max(1, j * 2), lim = p) {
best = max(best, {len, r[node] - len});
p = j, iota(all(y), n - j); struct AhoCorasick {
return mask;
rep(i,0,n) if (sa[i] >= j) y[p++] = sa[i] - j; enum {alpha = 26, first = ’A’}; // change t h i s !
}
fill(all(ws), 0); struct Node {
static pii LCS(string s, string t) {
rep(i,0,n) ws[x[i]]++; // (nmatches i s optional )
SuffixTree st(s + (char)(’z’ + 1) + t + (char)(’z’ + 2));
rep(i,1,lim) ws[i] += ws[i - 1]; int back, next[alpha], start = -1, end = -1, nmatches = 0;
st.lcs(0, sz(s), sz(s) + 1 + sz(t), 0);
for (int i = n; i--;) sa[--ws[x[y[i]]]] = y[i]; Node(int v) { memset(next, v, sizeof(next)); }
return st.best;
swap(x, y), p = 1, x[sa[0]] = 0; };
}
rep(i,1,n) a = sa[i - 1], b = sa[i], x[b] = vector<Node> N;
};
(y[a] == y[b] && y[a + j] == y[b + j]) ? p - 1 : p++; vi backp;
KTH IntervalContainer IntervalCover ConstantIntervals TernarySearch LIS FastKnapsack 22
void insert(string& s, int j) { set<pii>::iterator addInterval(set<pii>& is, int L, int R) { }
assert(!s.empty()); if (L == R) return is.end(); }
int n = 0; auto it = is.lower_bound({L, R}), before = it; template<class F, class G>
for (char c : s) { while (it != is.end() && it->first <= R) { void constantIntervals(int from, int to, F f, G g) {
int& m = N[n].next[c - first]; R = max(R, it->second); if (to <= from) return;
if (m == -1) { n = m = sz(N); N.emplace_back(-1); } before = it = is.erase(it); int i = from; auto p = f(i), q = f(to-1);
else n = m; } rec(from, to-1, f, g, i, p, q);
} if (it != is.begin() && (--it)->second >= L) { g(i, to, q);
if (N[n].end == -1) N[n].start = j; L = min(L, it->first); }
backp.push_back(N[n].end); R = max(R, it->second);
N[n].end = j;
N[n].nmatches++; }
is.erase(it); 10.2 Misc. algorithms
} return is.insert(before, {L,R}); TernarySearch.h
AhoCorasick(vector<string>& pat) : N(1, -1) { } Description: Find the smallest i in [a, b] that maximizes f (i), assuming
rep(i,0,sz(pat)) insert(pat[i], i); that f (a) < . . . < f (i) ≥ · · · ≥ f (b). To reverse which of the sides allows
N[0].back = sz(N); void removeInterval(set<pii>& is, int L, int R) { non-strict inequalities, change the < marked with (A) to <=, and reverse
N.emplace_back(0); if (L == R) return; the loop at (B). To minimize f , change it to >, also at (B).
auto it = addInterval(is, L, R); Usage: int ind = ternSearch(0,n-1,[&](int i){return a[i];});
queue<int> q; auto r2 = it->second; Time: O (log(b − a)) 9155b4, 11 lines
for (q.push(0); !q.empty(); q.pop()) { if (it->first == L) is.erase(it);
int n = q.front(), prev = N[n].back; else (int&)it->second = L; template<class F>
rep(i,0,alpha) { if (R != r2) is.emplace(R, r2); int ternSearch(int a, int b, F f) {
int &ed = N[n].next[i], y = N[prev].next[i]; } assert(a <= b);
if (ed == -1) ed = y; while (b - a >= 5) {
else { int mid = (a + b) / 2;
N[ed].back = y; IntervalCover.h if (f(mid) < f(mid+1)) a = mid; // (A)
(N[ed].end == -1 ? N[ed].end : backp[N[ed].start]) Description: Compute indices of smallest set of intervals covering another else b = mid+1;
= N[y].end; interval. Intervals should be [inclusive, exclusive). To support [inclusive, }
N[ed].nmatches += N[y].nmatches; inclusive], change (A) to add || R.empty(). Returns empty set on failure rep(i,a+1,b+1) if (f(a) < f(i)) a = i; // (B)
q.push(ed); (or if G is empty). return a;
} Time: O (N log N ) 9e9d8d, 19 lines
}
} template<class T>
} vi cover(pair<T, T> G, vector<pair<T, T>> I) { LIS.h
} vi S(sz(I)), R; Description: Compute indices for the longest increasing subsequence.
vi find(string word) { iota(all(S), 0); Time: O (N log N ) 2932a0, 17 lines
int n = 0; sort(all(S), [&](int a, int b) { return I[a] < I[b]; });
vi res; // l l count = 0; template<class I> vi lis(const vector<I>& S) {
T cur = G.first; if (S.empty()) return {};
for (char c : word) { int at = 0;
n = N[n].next[c - first]; vi prev(sz(S));
while (cur < G.second) { // (A) typedef pair<I, int> p;
res.push_back(N[n].end); pair<T, int> mx = make_pair(cur, -1);
// count += N[n ] . nmatches ; vector<p> res;
while (at < sz(I) && I[S[at]].first <= cur) { rep(i,0,sz(S)) {
}
return res;
mx = max(mx, make_pair(I[S[at]].second, S[at])); // change 0 => i for longest non=decreasing subsequence
at++; auto it = lower_bound(all(res), p{S[i], 0});
} }
vector<vi> findAll(vector<string>& pat, string word) { if (it == res.end()) res.emplace_back(), it = res.end()-1;
if (mx.second == -1) return {};
vi r = find(word); *it = {S[i], i};
cur = mx.first; prev[i] = it == res.begin() ? 0 : (it-1)->second;
vector<vi> res(sz(word)); R.push_back(mx.second);
rep(i,0,sz(word)) { }
} int L = sz(res), cur = res.back().second;
int ind = r[i]; return R;
while (ind != -1) { vi ans(L);
} while (L--) ans[L] = cur, cur = prev[cur];
res[i - sz(pat[ind]) + 1].push_back(ind);
ind = backp[ind]; return ans;
} ConstantIntervals.h }
} Description: Split a monotone function on [from, to) into a minimal set of
return res; half-open intervals on which it has the same value. Runs a callback g for FastKnapsack.h
} each such interval. Description: Given N non-negative integer weights w and a non-negative
}; Usage: constantIntervals(0, sz(v), [&](int x){return v[x];}, target t, computes the maximum S <= t such that S is the sum of some
[&](int lo, int hi, T val){...}); subset of the weights.
Time: O k log n k 753a4c, 19 lines
Time: O (N max(wi )) b20ccc, 16 lines
Various (10) template<class F, class G, class T> int knapsack(vi w, int t) {
void rec(int from, int to, F& f, G& g, int& i, T& p, T q) { int a = 0, b = 0, x;
if (p == q) return; while (b < sz(w) && a + w[b] <= t) a += w[b++];
10.1 Intervals if (from == to) { if (b == sz(w)) return a;
IntervalContainer.h g(i, to, p); int m = *max_element(all(w));
Description: Add and remove intervals from a set of disjoint intervals. i = to; p = q; vi u, v(2*m, -1);
Will merge the added interval with any overlapping intervals in the set when } else { v[a+m-t] = b;
adding. Intervals are [inclusive, exclusive). int mid = (from + to) >> 1; rep(i,b,sz(w)) {
Time: O (log N ) edce47, 23 lines
rec(from, mid, f, g, i, p, f(mid)); u = v;
rec(mid+1, to, f, g, i, p, q); rep(x,0,m) v[x+w[i]] = max(v[x+w[i]], u[x]);
KTH KnuthDP DivideAndConquerDP FastMod FastInput BumpAllocator SmallPtr BumpAllocatorSTL SIMD 23
for (x = 2*m; --x > m;) rep(j, max(0,u[x]), v[x]) ˆ c = x&-x, r = x+c; (((rˆx) >> 2)/c) | r is the }
v[x-w[j]] = max(v[x-w[j]], j); next number after x with the same number of bits set. void operator delete(void*) {}
}
for (a = t; v[a+m-t] < 0; a--) ;
return a;
ˆ rep(b,0,K) rep(i,0,(1 << K)) SmallPtr.h
Description: A 32-bit pointer that points into BumpAllocator memory.
} if (i & 1 << b) D[i] += D[iˆ(1 << b)]; "BumpAllocator.h" 2dd6c9, 10 lines
computes all sums of subsets. template<class T> struct ptr {
10.3 Dynamic programming 10.5.2 Pragmas unsigned ind;
ptr(T* p = 0) : ind(p ? unsigned((char*)p - buf) : 0) {
KnuthDP.h assert(ind < sizeof buf);
Description: When doing DP on intervals: a[i][j] = mini<k<j (a[i][k] + ˆ #pragma GCC optimize ("Ofast") will make GCC }
a[k][j]) + f (i, j), where the (minimal) optimal k increases with both i
and j, one can solve intervals in increasing order of length, and search
auto-vectorize loops and optimizes floating points better. T& operator*() const { return *(T*)(buf + ind); }
T* operator->() const { return &**this; }
k = p[i][j] for a[i][j] only between p[i][j − 1] and p[i + 1][j]. This is
known as Knuth DP. Sufficient criteria for this are if f (b, c) ≤ f (a, d) and ˆ #pragma GCC target ("avx2") can double performance of T& operator[](int a) const { return (&**this)[a]; }
explicit operator bool() const { return ind; }
f (a, c) + f (b, d) ≤ f (a, d) + f (b, c) for all a ≤ b ≤ c ≤ d. Consider also: vectorized code, but causes crashes on old machines. };
LineContainer(ch. Data structures), monotone queues, ternary search.
Time: O N 2 ˆ #pragma GCC optimize ("trapv") kills the program on integer
BumpAllocatorSTL.h
overflows (but is really slow). Description: BumpAllocator for STL containers.
Usage: vector<vector<int, small<int>>> ed(N);
DivideAndConquerDP.h FastMod.h bb66d4, 14 lines
Description: Given a[i] = minlo(i)≤k<hi(i) (f (i, k)) where the (minimal) Description: Compute a%b about 5 times faster than usual, where b is char buf[450 << 20] alignas(16);
optimal k increases with i, computes a[i] for i = L..R − 1. constant but not known at compile time. Returns a value congruent to a size_t buf_ind = sizeof buf;
Time: O ((N + (hi − lo)) log N ) d38d2b, 18 lines (mod b) in the range [0, 2b). 751a02, 8 lines
template<class T> struct small {
struct DP { // Modify at w i l l : typedef unsigned long long ull; typedef T value_type;
int lo(int ind) { return 0; } struct FastMod { small() {}
int hi(int ind) { return ind; } ull b, m; template<class U> small(const U&) {}
ll f(int ind, int k) { return dp[ind][k]; } FastMod(ull b) : b(b), m(-1ULL / b) {} T* allocate(size_t n) {
void store(int ind, int k, ll v) { res[ind] = pii(k, v); } ull reduce(ull a) { // a % b + (0 or b) buf_ind -= n * sizeof(T);
return a - (ull)((__uint128_t(m) * a) >> 64) * b; buf_ind &= 0 - alignof(T);
void rec(int L, int R, int LO, int HI) { } return (T*)(buf + buf_ind);
if (L >= R) return; }; }
int mid = (L + R) >> 1;
void deallocate(T*, size_t) {}
pair<ll, int> best(LLONG_MAX, LO);
rep(k, max(LO,lo(mid)), min(HI,hi(mid))) FastInput.h };
best = min(best, make_pair(f(mid, k), k)); Description: Read an integer from stdin. Usage requires your program to
store(mid, best.second, best.first); pipe in input from file. SIMD.h
rec(L, mid, LO, best.second+1); Usage: ./a.out < input.txt Description: Cheat sheet of SSE/AVX intrinsics, for doing arithmetic
rec(mid+1, R, best.second, HI); Time: About 5x as fast as cin/scanf. 7b3c70, 17 lines
on several numbers at once. Can provide a constant factor improvement
} of about 4, orthogonal to loop unrolling. Operations follow the pat-
inline char gc() { // l i k e getchar () tern " mm(256)? name (si(128|256)|epi(8|16|32|64)|pd|ps)". Not all
void solve(int L, int R) { rec(L, R, INT_MIN, INT_MAX); } static char buf[1 << 16];
}; are described here; grep for mm in /usr/lib/gcc/*/4.9/include/ for
static size_t bc, be; more. If AVX is unsupported, try 128-bit operations, ”emmintrin.h” and
if (bc >= be) { #define SSE and MMX before including it. For aligned memory use
10.4 Debugging tricks buf[0] = 0, bc = 0; mm malloc(size, 32) or int buf[N] alignas(32), but prefer loadu/s-
be = fread(buf, 1, sizeof(buf), stdin); toreu.
ˆ signal(SIGSEGV, [](int) { _Exit(0); }); } 551b82, 43 lines
return buf[bc++]; // returns 0 on EOF #pragma GCC target ("avx2") // or sse4 .1
converts segfaults into Wrong Answers. Similarly one can } #include "immintrin.h"
catch SIGABRT (assertion failures) and SIGFPE (zero
divisions). _GLIBCXX_DEBUG failures generate SIGABRT int readInt() { typedef __m256i mi;
int a, c; #define L(x) _mm256_loadu_si256((mi*)&(x))
(or SIGSEGV on gcc 5.4.0 apparently). while ((a = gc()) < 40);
if (a == ’-’) return -readInt(); // High=l e v e l / s p e c i f i c methods :
ˆ feenableexcept(29); kills the program on NaNs (1), while ((c = gc()) >= 48) a = a * 10 + c - 480; // load (u)? si256 , store (u)? si256 , setzero si256 , mm malloc
0-divs (4), infinities (8) and denormals (16). return a - 48; // blendv ( epi8 | ps | pd) ( z?y : x) , movemask epi8 ( h i b i t s of bytes )
} // i32gather epi32 (addr , x , 4) : map addr [ ] over 32=b parts of x
// sad epu8 : sum of absolute differences of u8, outputs 4xi64
10.5 Optimization tricks // maddubs epi16 : dot product of unsigned i7 ’ s , outputs 16xi15
BumpAllocator.h
__builtin_ia32_ldmxcsr(40896); disables denormals Description: When you need to dynamically allocate many objects and // madd epi16 : dot product of signed i16 ’ s , outputs 8xi32
// extractf128 si256 ( , i ) (256=>128) , cvtsi128 si32 (128=>lo32 )
(which make floats 20x slower near their minimum value). don’t care about freeing them. ”new X” otherwise has an overhead of some-
// permute2f128 si256(x , x ,1) swaps 128= b i t lanes
thing like 0.05us + 16 bytes per allocation.
10.5.1 Bit hacks 745db2, 8 lines // shuffle epi32 (x , 3*64+2*16+1*4+0) == x for each lane
// Either g l o b a l l y or in a single class : // s h u f f l e e p i 8 (x , y) takes a vector instead of an imm
ˆ x & -x is the least bit in x. static char buf[450 << 20];
void* operator new(size_t s) { // Methods that work with most data types (append e . g . epi32 ) :
static size_t i = sizeof buf; // set1 , blend ( i8?x : y) , add , adds ( sat . ) , mullo , sub , and/or ,
ˆ for (int x = m; x; ) { --x &= m; ... } loops assert(s < i); // andnot , abs , min, max, sign (1 ,x) , cmp( gt | eq) , unpack( lo | hi )
over all subset masks of m (except m itself). return (void*)&buf[i -= s];
KTH 24
int sumi32(mi m) { union {int v[8]; mi m;} u; u.m = m;
int ret = 0; rep(i,0,8) ret += u.v[i]; return ret; }
mi zero() { return _mm256_setzero_si256(); }
mi one() { return _mm256_set1_epi32(-1); }
bool all_zero(mi m) { return _mm256_testz_si256(m, m); }
bool all_one(mi m) { return _mm256_testc_si256(m, one()); }

ll example_filteredDotProduct(int n, short* a, short* b) {


int i = 0; ll r = 0;
mi zero = _mm256_setzero_si256(), acc = zero;
while (i + 16 <= n) {
mi va = L(a[i]), vb = L(b[i]); i += 16;
va = _mm256_and_si256(_mm256_cmpgt_epi16(vb, va), va);
mi vp = _mm256_madd_epi16(va, vb);
acc = _mm256_add_epi64(_mm256_unpacklo_epi32(vp, zero),
_mm256_add_epi64(acc, _mm256_unpackhi_epi32(vp, zero)));
}
union {ll v[4]; mi m;} u; u.m = acc; rep(i,0,4) r += u.v[i];
for (;i<n;++i) if (a[i] < b[i]) r += a[i]*b[i]; // <= equiv
return r;
}
KTH techniques 25

Techniques (A) Computation of binomial coefficients


Pigeon-hole principle
Knuth-Morris-Pratt
Tries
Inclusion/exclusion Rolling polynomial hashes
techniques.txt 159 lines
Catalan number Suffix array
Pick’s theorem Suffix tree
Recursion Number theory Aho-Corasick
Divide and conquer Integer parts Manacher’s algorithm
Finding interesting points in N log N Divisibility Letter position lists
Algorithm analysis Euclidean algorithm Combinatorial search
Master theorem Modular arithmetic Meet in the middle
Amortized time complexity
Greedy algorithm * Modular multiplication Brute-force with pruning
Scheduling * Modular inverses Best-first (A*)
Max contiguous subvector sum * Modular exponentiation by squaring Bidirectional search
Chinese remainder theorem Iterative deepening DFS / A*
Invariants Fermat’s little theorem Data structures
Huffman encoding Euler’s theorem LCA (2^k-jumps in trees in general)
Graph theory Phi function Pull/push-technique on trees
Dynamic graphs (extra book-keeping) Frobenius number Heavy-light decomposition
Breadth first search Quadratic reciprocity Centroid decomposition
Depth first search Pollard-Rho Lazy propagation
* Normal trees / DFS trees Miller-Rabin Self-balancing trees
Dijkstra’s algorithm Hensel lifting Convex hull trick (wcipeg.com/wiki/Convex_hull_trick)
MST: Prim’s algorithm Vieta root jumping Monotone queues / monotone stacks / sliding queues
Bellman-Ford Game theory Sliding queue using 2 stacks
Konig’s theorem and vertex cover Combinatorial games Persistent segment tree
Min-cost max flow Game trees
Lovasz toggle Mini-max
Matrix tree theorem Nim
Maximal matching, general graphs Games on graphs
Hopcroft-Karp Games on graphs with loops
Hall’s marriage theorem Grundy numbers
Graphical sequences Bipartite games without repetition
Floyd-Warshall General games without repetition
Euler cycles Alpha-beta pruning
Flow networks Probability theory
* Augmenting paths Optimization
* Edmonds-Karp Binary search
Bipartite matching Ternary search
Min. path cover Unimodality and convex functions
Topological sorting Binary search on derivative
Strongly connected components Numerical methods
2-SAT Numeric integration
Cut vertices, cut-edges and biconnected components Newton’s method
Edge coloring Root-finding with binary/ternary search
* Trees Golden section search
Vertex coloring Matrices
* Bipartite graphs (=> trees) Gaussian elimination
* 3^n (special case of set cover) Exponentiation by squaring
Diameter and centroid Sorting
K’th shortest path Radix sort
Shortest cycle Geometry
Dynamic programming Coordinates and vectors
Knapsack
Coin change * Cross product
Longest common subsequence * Scalar product
Convex hull
Longest increasing subsequence Polygon cut
Number of paths in a dag Closest pair
Shortest path in a dag Coordinate-compression
Dynprog over intervals Quadtrees
Dynprog over subsets KD-trees
Dynprog over probabilities All segment-segment intersection
Dynprog over trees Sweeping
3^n set cover Discretization (convert to events and sweep)
Divide and conquer Angle sweeping
Knuth optimization Line sweeping
Convex hull optimizations Discrete second derivatives
RMQ (sparse table a.k.a 2^k-jumps) Strings
Bitonic cycle Longest common substring
Log partitioning (loop over most restricted) Palindrome subsequences
Combinatorics

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy