Académique Documents
Professionnel Documents
Culture Documents
Omogen Heap
Simon Lindholm, Johan Sannemo, Mårten Wiman
2019-05-21
1 Contest 1 troubleshoot.txt 52 lines
Pre-submit: ed − bf
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. ⇒
Is the memory usage fine? cx + dy = f af − ec
3 Data structures 3 Could anything overflow? y=
Make sure to submit the right file.
ad − bc
4 Numerical 5 Wrong answer:
Print your solution! Print debug output, as well.
In general, given an equation Ax = b, the solution to a
5 Number theory 8 Are you clearing all datastructures between test cases? variable xi is given by
Can your algorithm handle the whole range of input?
Read the full problem statement again.
6 Combinatorial 10 Do you handle all corner cases correctly? det A0i
Have you understood the problem correctly? xi =
Any uninitialized variables?
det A
7 Graph 11 Any overflows?
Confusing N and M, i and j, etc.? where A0i is A with the i’th column replaced by b.
Are you sure your algorithm works?
8 Geometry 17 What special cases have you not thought of?
Are you sure the STL functions you use work as you think? 2.2 Recurrences
9 Strings 20 Add some assertions, maybe resubmit.
Create some testcases to run your algorithm on.
Go through the algorithm for a simple case. If an = c1 an−1 + · · · + ck an−k , and r1 , . . . , rk are distinct
10 Various 22 Go through this list again. roots of xk + c1 xk−1 + · · · + ck , there are d1 , . . . , dk s.t.
Explain your algorithm to a team mate.
Ask the team mate to look at your code.
Contest (1) Go for a small walk, e.g. to the toilet.
Is your output format correct? (including whitespace)
an = d1 r1n + · · · + dk rkn .
Rewrite your solution from the start or let a team mate do it.
template.cpp 15 lines Non-distinct roots r become polynomial factors, e.g.
Runtime error:
#include <bits/stdc++.h>
Have you tested all corner cases locally? an = (d1 n + d2 )rn .
using namespace std;
Any uninitialized variables?
#define rep(i, a, b) for(int i = a; i < (b); ++i) Are you reading or writing outside the range of any vector?
#define trav(a, x) for(auto& a : x) Any assertions that might fail? 2.3 Trigonometry
#define all(x) begin(x), end(x) Any possible division by 0? (mod 0 for example)
#define sz(x) (int)(x).size() Any possible infinite recursion?
typedef long long ll; Invalidated pointers or iterators?
typedef pair<int, int> pii; Are you using too much memory? sin(v + w) = sin v cos w + cos v sin w
typedef vector<int> vi; Debug with resubmits (e.g. remapped signals, see Various).
cos(v + w) = cos v cos w − sin v sin w
int main() { Time limit exceeded:
cin.sync_with_stdio(0); cin.tie(0); Do you have any possible infinite loops?
cin.exceptions(cin.failbit); What is the complexity of your algorithm?
} Are you copying a lot of unnecessary data? (References)
How big is the input and output? (consider scanf)
Avoid vector, map. (use arrays/unordered_map) tan v + tan w
.bashrc What do your team mates think about your algorithm? tan(v + w) =
3 lines 1 − tan v tan w
alias c=’g++ -Wall -Wconversion -Wfatal-errors -g -std=c++14 \ Memory limit exceeded: v+w v−w
-fsanitize=undefined,address’ What is the max amount of memory your algorithm should need? sin v + sin w = 2 sin cos
xmodmap -e ’clear lock’ -e ’keycode 66=less greater’ #caps = <> Are you clearing all datastructures between test cases? 2 2
v+w v−w
.vimrc cos v + cos w = 2 cos cos
6 lines 2 2
set cin aw ai is ts=4 sw=4 tm=50 nu noeb bg=dark ru cul Mathematics (2)
sy on | im jk <esc> | im kj <esc> | no ; : (V + W ) tan(v − w)/2 = (V − W ) tan(v + w)/2
" Select region and then type :Hash to hash your selection.
" Useful for verifying that there aren’t mistypes. 2.1 Equations
ca Hash w !cpp -dD -P -fpreprocessed \| tr -d ’[:space:]’ \ where V, W are lengths of sides opposite angles v, w.
\| md5sum \| cut -c-6 √
−b ± b2 − 4ac a cos x + b sin x = r cos(x − φ)
hash.sh ax2 + bx + c = 0 ⇒ x =
3 lines 2a a sin x + b cos x = r sin(x + φ)
# Hashes a file, ignoring all whitespace and comments. Use for
# verifying that code was correctly typed.
cpp -dD -P -fpreprocessed | tr -d ’[:space:]’| md5sum |cut -c-6
√
The extremum is given by x = −b/2a. where r = a2 + b2 , φ = atan2(b, a).
KTH template .bashrc .vimrc hash troubleshoot 2
2.4 Geometry 2.5 Derivatives/Integrals 2.8 Probability theory
2.4.1 Triangles Let X be a discrete random variable with probability pX (x)
d 1 d 1 of assuming the valuePx. It will then have an expected value
arcsin x = √ arccos x = − √
Side lengths: a, b, c dx 1 − x2 dx 1 − x2 (mean) µ = E(X) = x xpX (x) and
a+b+c P variance
Semiperimeter: p = d d 1 σ 2 = V (X) = E(X 2 ) − (E(X))2 = x (x − E(X))2 pX (x)
2 tan x = 1 + tan2 x arctan x = where σ is the standard deviation. If X is instead
p dx dx 1 + x2
Area: A = p(p − a)(p − b)(p − c) continuous it will have a probability density function fX (x)
ln | cos ax| sin ax − ax cos ax
Z Z
abc tan ax = − x sin ax = and the sums above will instead be integrals with pX (x)
Circumradius: R = a a2
4A √ replaced by fX (x).
A eax
Z Z
2 π
Inradius: r = e−x = erf(x) xeax dx = 2 (ax − 1)
p 2 a Expectation is linear:
Length of median (divides
√ triangle into two equal-area
triangles): ma = 21 2b2 + 2c2 − a2 E(aX + bY ) = aE(X) + bE(Y )
Integration by parts:
Length
v of "bisector (divides angles in two): For independent X and Y ,
2 # Z b Z b
V (aX + bY ) = a2 V (X) + b2 V (Y ).
u
u a f (x)g(x)dx = [F (x)g(x)]ba − F (x)g 0 (x)dx
sa = tbc 1 −
b+c a a
2.8.1 Discrete distributions
sin α sin β sin γ 1
Law of sines: = = = 2.6 Sums
a b c 2R Binomial distribution
Law of cosines: a2 = b2 + c2 − 2bc cos α c b+1
−c a
α+β ca + ca+1 + · · · + cb = , c 6= 1 The number of successes in n independent yes/no
a+b tan c−1
Law of tangents: = 2 experiments, each which yields success with probability p is
a−b α−β Bin(n, p), n = 1, 2, . . . , 0 ≤ p ≤ 1.
tan n(n + 1)
2 1 + 2 + 3 + ··· + n =
2 n k
2.4.2 Quadrilaterals p(k) = p (1 − p)n−k
n(2n + 1)(n + 1) k
12 + 22 + 32 + · · · + n2 =
With side lengths a, b, c, d, diagonals e, f , diagonals angle θ, 6 µ = np, σ 2 = np(1 − p)
2 2
area A and magic flux F = b2 + d2 − a2 − c2 : n (n + 1)
13 + 23 + 33 + · · · + n3 = Bin(n, p) is approximately Po(np) for small p.
4
p 4 4 4 4 n(n + 1)(2n + 1)(3n2 + 3n − 1) First success distribution
4A = 2ef · sin θ = F tan θ = 4e2 f 2 − F 2 1 + 2 + 3 + ··· + n =
30
The number of trials needed to get the first success in
For cyclic quadrilateralspthe sum of opposite angles is 180◦ , independent yes/no experiments, each wich yields success
ef = ac + bd, and A = (p − a)(p − b)(p − c)(p − d). with probability p is Fs(p), 0 ≤ p ≤ 1.
2.7 Series
2.4.3 Spherical coordinates p(k) = p(1 − p)k−1 , k = 1, 2, . . .
z x x2 x3
e =1+x+ + + . . . , (−∞ < x < ∞) 1 2 1−p
2! 3! µ= ,σ =
r x2 x3 x4
p p2
y ln(1 + x) = x − + − + . . . , (−1 < x ≤ 1)
2 3 4 Poisson distribution
x √ x x 2
2x 3
5x 4
1+x=1+ − + − + . . . , (−1 ≤ x ≤ 1) The number of events occurring in a fixed period of time t if
2 8 32 128 these events occur with a known average rate κ and
x3 x5 x7 independently of the time since the last event is
sin x = x − + − + . . . , (−∞ < x < ∞)
Po(λ), λ = tκ.
p
x = r sin θ cos φ r = xp 2 + y2 + z2 3! 5! 7!
y = r sin θ sin φ θ = acos(z/ x2 + y 2 + z 2 ) x2 x4 x6 λk
z = r cos θ φ = atan2(y, x) cos x = 1 − + − + . . . , (−∞ < x < ∞) p(k) = e−λ , k = 0, 1, 2, . . .
2! 4! 6! k!
KTH OrderStatisticTree HashMap SegmentTree LazySegmentTree 3
2
µ = λ, σ = λ π is a stationary distribution if π = πP. If the Markov chain SegmentTree.h
Description: Zero-indexed max-tree. Bounds are inclusive to the left and
is irreducible (it is possible to get to any state from any exclusive to the right. Can be changed by modifying T, f and unit.
1
2.8.2 Continuous distributions state), then πi = E(Ti ) where E(Ti ) is the expected time Time: O (log N ) 0f4bdb, 19 lines
between two visits in state i. πj /πi is the expected number struct Tree {
Uniform distribution typedef int T;
of visits in state j between two visits in state i. static constexpr T unit = INT_MIN;
T f(T a, T b) { return max(a, b); } // (any associative fn )
If the probability density function is constant between a and For a connected, undirected and non-bipartite graph, where vector<T> s; int n;
b and 0 elsewhere it is U(a, b), a < b. the transition probability is uniform among all neighbors, πi Tree(int n = 0, T def = unit) : s(2*n, def), n(n) {}
void update(int pos, T val) {
1 is proportional to node i’s degree. for (s[pos += n] = val; pos /= 2;)
b−a a<x<b s[pos] = f(s[pos * 2], s[pos * 2 + 1]);
f (x) = }
0 otherwise A Markov chain is ergodic if the asymptotic distribution is T query(int b, int e) { // query [ b , e)
independent of the initial distribution. A finite Markov T ra = unit, rb = unit;
for (b += n, e += n; b < e; b /= 2, e /= 2) {
a+b 2 (b − a)2 chain is ergodic iff it is irreducible and aperiodic (i.e., the if (b % 2) ra = f(ra, s[b++]);
µ= ,σ =
2 12 gcd of cycle lengths is 1). limk→∞ Pk = 1π. if (e % 2) rb = f(s[--e], rb);
}
return f(ra, rb);
Exponential distribution A Markov chain is an A-chain if the states can be }
partitioned into two sets A and G, such that all states in A };
The time between events in a Poisson process is are absorbing (pii = 1), and all states in G leads to an
Exp(λ), λ > 0. absorbing state in A. The probability for absorption
P in state LazySegmentTree.h
Description: Segment tree with ability to add or set values of large intervals,
i ∈ A, when the initial state is j, is aij = pij + k∈G aik pkj . and compute max of intervals. Can be changed to other things. Use with a
λe−λx x ≥ 0 time until absorption, when the initial state is bump allocator for better performance, and SmallPtr or implicit indices to
The expectedP
f (x) = save memory.
0 x<0 i, is ti = 1 + k∈G pki tk . Usage: Node* tr = new Node(v, 0, sz(v));
Time: O (log N ).
"../various/BumpAllocator.h" 34ecf5, 50 lines
1 1 Data structures (3)
µ = , σ2 = 2 const int inf = 1e9;
λ λ struct Node {
Node *l = 0, *r = 0;
OrderStatisticTree.h int lo, hi, mset = inf, madd = 0, val = -inf;
Normal distribution Description: A set (not multiset!) with support for finding the n’th ele-
Node(int lo,int hi):lo(lo),hi(hi){} // Large interval of −in f
ment, and finding the index of an element. To get a map, change null type.
Node(vi& v, int lo, int hi) : lo(lo), hi(hi) {
Time: O (log N ) 782797, 16 lines if (lo + 1 < hi) {
Most real random values with mean µ and variance σ 2 are #include <bits/extc++.h> int mid = lo + (hi - lo)/2;
well described by N (µ, σ 2 ), σ > 0. using namespace __gnu_pbds; l = new Node(v, lo, mid); r = new Node(v, mid, hi);
val = max(l->val, r->val);
template<class T> }
1 (x−µ)2
f (x) = √ e− 2σ 2 using Tree = tree<T, null_type, less<T>, rb_tree_tag,
tree_order_statistics_node_update>; }
else val = v[lo];
2πσ 2 int query(int L, int R) {
void example() { if (R <= lo || hi <= L) return -inf;
If X1 ∼ N (µ1 , σ12 ) and X2 ∼ N (µ2 , σ22 ) then Tree<int> t, t2; t.insert(8); if (L <= lo && hi <= R) return val;
auto it = t.insert(10).first; push();
assert(it == t.lower_bound(9)); return max(l->query(L, R), r->query(L, R));
aX1 + bX2 + c ∼ N (µ1 + µ2 + c, a2 σ12 + b2 σ22 ) assert(t.order_of_key(10) == 1); }
assert(t.order_of_key(11) == 2); void set(int L, int R, int x) {
assert(*t.find_by_order(0) == 8); if (R <= lo || hi <= L) return;
t.join(t2); // assuming T < T2 or T > T2, merge t2 into t if (L <= lo && hi <= R) mset = val = x, madd = 0;
2.9 Markov chains } else {
push(), l->set(L, R, x), r->set(L, R, x);
A Markov chain is a discrete random process with the HashMap.h
val = max(l->val, r->val);
}
property that the next state depends only on the current Description: Hash map with the same API as unordered map, but ∼3x }
state. Let X1 , X2 , . . . be a sequence of random variables faster. Initial capacity must be a power of 2 (if provided). 1443bc, 7 lines void add(int L, int R, int x) {
if (R <= lo || hi <= L) return;
generated by the Markov process. Then there is a transition #include <bits/extc++.h>
if (L <= lo && hi <= R) {
// To use most b i t s rather than j u s t the lowest ones :
matrix P = (pij ), with pij = Pr(Xn = i|Xn−1 = j), and struct chash {
if (mset != inf) mset += x;
else madd += x;
p(n) = Pn p(0) is the probability distribution for Xn (i.e., const uint64_t C = ll(2e18 * M_PI) + 71; // large odd number
val += x;
(n) ll operator()(ll x) const { return __builtin_bswap64(x*C); }
pi = Pr(Xn = i)), where p(0) is the initial };
}
else {
__gnu_pbds::gp_hash_table<ll,int,chash> h({},{},{},{},{1<<16});
distribution. push(), l->add(L, R, x), r->add(L, R, x);
KTH UnionFind SubMatrix Matrix LineContainer Treap FenwickTree 4
val = max(l->val, r->val); return a; void Node::recalc() { c = cnt(l) + cnt(r) + 1; }
} }
} vector<T> operator*(const vector<T>& vec) const { template<class F> void each(Node* n, F f) {
void push() { vector<T> ret(N); if (n) { each(n->l, f); f(n->val); each(n->r, f); }
if (!l) { rep(i,0,N) rep(j,0,N) ret[i] += d[i][j] * vec[j]; }
int mid = lo + (hi - lo)/2; return ret;
l = new Node(lo, mid); r = new Node(mid, hi); } pair<Node*, Node*> split(Node* n, int k) {
} M operatorˆ(ll p) const { if (!n) return {};
if (mset != inf) assert(p >= 0); if (cnt(n->l) >= k) { // ”n−>val >= v” for lower bound(v)
l->set(lo,hi,mset), r->set(lo,hi,mset), mset = inf; M a, b(*this); auto pa = split(n->l, k);
else if (madd) rep(i,0,N) a.d[i][i] = 1; n->l = pa.second;
l->add(lo,hi,madd), r->add(lo,hi,madd), madd = 0; while (p) { n->recalc();
} if (p&1) a = a*b; return {pa.first, n};
}; b = b*b; } else {
p >>= 1; auto pa = split(n->r, k - cnt(n->l) - 1);
} n->r = pa.first;
UnionFind.h return a; n->recalc();
Description: Disjoint-set data structure.
} return {n, pa.second};
Time: O (α(N )) b5bfc3, 14 lines }; }
struct UF { }
vi e;
UF(int n) : e(n, -1) {}
LineContainer.h Node* merge(Node* l, Node* r) {
Description: Container where you can add lines of the form kx+m, and if (!l) return r;
bool same_set(int a, int b) { return find(a) == find(b); }
query maximum values at points x. Useful for dynamic programming. if (!r) return l;
int size(int x) { return -e[find(x)]; }
Time: O (log N ) 95e223, 30 lines if (l->y > r->y) {
int find(int x) { return e[x] < 0 ? x : e[x] = find(e[x]); }
bool join(int a, int b) { struct Line { l->r = merge(l->r, r);
a = find(a), b = find(b); mutable ll k, m, p; l->recalc();
if (a == b) return false; bool operator<(const Line& o) const { return k < o.k; } return l;
if (e[a] > e[b]) swap(a, b); bool operator<(ll x) const { return p < x; } } else {
e[a] += e[b]; e[b] = a; }; r->l = merge(l, r->l);
return true; r->recalc();
} struct LineContainer : multiset<Line, less<>> { return r;
}; // ( for doubles , use i n f = 1/.0 , div (a , b) = a/b) }
const ll inf = LLONG_MAX; }
ll div(ll a, ll b) { // floored division
SubMatrix.h return a / b - ((a ˆ b) < 0 && a % b); } Node* ins(Node* t, Node* n, int pos) {
Description: Calculate submatrix sums quickly, given upper-left and lower- auto pa = split(t, pos);
bool isect(iterator x, iterator y) {
right corners (half-open). return merge(merge(pa.first, n), pa.second);
if (y == end()) { x->p = inf; return false; }
Usage: SubMatrix<int> m(matrix); }
if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
m.sum(0, 0, 2, 2); // top left 4 elements
else x->p = div(y->m - x->m, x->k - y->k);
Time: O N 2 + Q
c59ada, 13 lines return x->p >= y->p; // Example application : move the range [ l , r ) to index k
template<class T> } void move(Node*& t, int l, int r, int k) {
struct SubMatrix { void add(ll k, ll m) { Node *a, *b, *c;
vector<vector<T>> p; auto z = insert({k, m, 0}), y = z++, x = y; tie(a,b) = split(t, l); tie(b,c) = split(b, r - l);
SubMatrix(vector<vector<T>>& v) { while (isect(y, z)) z = erase(z); if (k <= l) t = merge(ins(a, b, k), c);
int R = sz(v), C = sz(v[0]); if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); else t = merge(a, ins(c, b, k - r));
p.assign(R+1, vector<T>(C+1)); while ((y = x) != begin() && (--x)->p >= y->p) }
rep(r,0,R) rep(c,0,C) isect(x, erase(y));
p[r+1][c+1] = v[r][c] + p[r][c+1] + p[r+1][c] - p[r][c]; }
} ll query(ll x) { FenwickTree.h
assert(!empty()); Description: Computes partial sums a[0] + a[1] + ... + a[pos - 1], and
T sum(int u, int l, int d, int r) {
auto l = *lower_bound(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];
return l.k * x + l.m; value.
}
} Time: Both operations are O (log N ).
}; e62fac, 22 lines
}; struct FT {
Matrix.h vector<ll> s;
Description: Basic operations on square matrices. Treap.h FT(int n) : s(n) {}
Usage: Matrix<int, 3> A; Description: A short self-balancing tree. It acts as a sequential container void update(int pos, ll dif) { // a [ pos ] += d i f
A.d = {{{{1,2,3}}, {{4,5,6}}, {{7,8,9}}}}; with log-time splits/joins, and is easy to augment with additional data. for (; pos < sz(s); pos |= pos + 1) s[pos] += dif;
vector<int> vec = {1,2,3}; Time: O (log N ) }
9556fc, 55 lines ll query(int pos) { // sum of values in [0 , pos)
vec = (AˆN) * vec; c43c7d, 26 lines struct Node { ll res = 0;
template<class T, int N> struct Matrix { Node *l = 0, *r = 0; for (; pos > 0; pos &= pos - 1) res += s[pos-1];
typedef Matrix M; int val, y, c = 1; return res;
array<array<T, N>, N> d{}; Node(int val) : val(val), y(rand()) {} }
M operator*(const M& m) const { void recalc(); int lower_bound(ll sum) {// min pos s t sum of [0 , pos ] >= sum
M a; }; // Returns n i f no sum i s >= sum, or −1 i f empty sum i s .
rep(i,0,N) rep(j,0,N) if (sum <= 0) return -1;
rep(k,0,N) a.d[i][j] += d[i][k]*m.d[k][j]; int cnt(Node* n) { return n ? n->c : 0; } int pos = 0;
KTH FenwickTree2d RMQ GoldenSectionSearch Polynomial PolyRoots PolyInterpolate BerlekampMassey LinearRecurrence 5
for (int pw = 1 << 25; pw; pw >>= 1) { GoldenSectionSearch.h ret.push_back((l + h) / 2);
if (pos + pw <= sz(s) && s[pos + pw-1] < sum) Description: Finds the argument minimizing the function f in the inter- }
pos += pw, sum -= s[pos-1]; val [a, b] assuming f is unimodal on the interval, i.e. has only one local }
} minimum. The maximum error in the result is eps. Works equally well for return ret;
return pos; maximization with a small change in the code. See TernarySearch.h in the }
} Various chapter for a discrete version.
}; Usage: double func(double x) { return 4+x+.3*x*x; }
double xmin = gss(-1000,1000,func);
PolyInterpolate.h
Description: Given n points (x[i], y[i]), computes an n-1-degree polynomial
Time: O (log((b − a)/)) 31d45b, 14 lines
p that passes through them: p(x) = a[0] ∗ x0 + ... + a[n − 1] ∗ xn−1 . For
FenwickTree2d.h double gss(double a, double b, double (*f)(double)) { numerical precision, pick x[k] = c ∗ cos(k/(n − 1) ∗ π), k = 0 . . . n − 1.
Description: Computes sums a[i,j] for all i<I, j<J, and increases single ele- double r = (sqrt(5)-1)/2, eps = 1e-7; Time: O n2
ments a[i,j]. Requires that the elements to be updated are known in advance 08bf48, 13 lines
double x1 = b - r*(b-a), x2 = a + r*(b-a);
(call fakeUpdate() before init()). double f1 = f(x1), f2 = f(x2); typedef vector<double> vd;
Time: O log2 N . (Use persistent segment trees for O (log N ).) while (b-a > eps) vd interpolate(vd x, vd y, int n) {
"FenwickTree.h" b28c27, 22 lines
if (f1 < f2) { //change to > to find maximum vd res(n), temp(n);
struct FT2 { b = x2; x2 = x1; f2 = f1; rep(k,0,n-1) rep(i,k+1,n)
vector<vi> ys; vector<FT> ft; x1 = b - r*(b-a); f1 = f(x1); y[i] = (y[i] - y[k]) / (x[i] - x[k]);
FT2(int limx) : ys(limx) {} } else { double last = 0; temp[0] = 1;
void fakeUpdate(int x, int y) { a = x1; x1 = x2; f1 = f2; rep(k,0,n) rep(i,0,n) {
for (; x < sz(ys); x |= x + 1) ys[x].push_back(y); x2 = a + r*(b-a); f2 = f(x2); res[i] += y[k] * temp[i];
} } swap(last, temp[i]);
void init() { return a; temp[i] -= last * x[k];
trav(v, ys) sort(all(v)), ft.emplace_back(sz(v)); } }
} return res;
int ind(int x, int y) { }
return (int)(lower_bound(all(ys[x]), y) - ys[x].begin()); } Polynomial.h c9b7b0, 17 lines
void update(int x, int y, ll dif) { BerlekampMassey.h
for (; x < sz(ys); x |= x + 1) struct Poly {
vector<double> a; Description: Recovers any n-order linear recurrence relation from the first
ft[x].update(ind(x, y), dif); 2n terms of the recurrence. Useful for guessing linear recurrences after brute-
} double operator()(double x) const {
double val = 0; forcing the first terms. Should work on any field, but numerical stability for
ll query(int x, int y) { floats is not guaranteed. Output will have size ≤ n.
ll sum = 0; for(int i = sz(a); i--;) (val *= x) += a[i];
return val; Usage: BerlekampMassey({0, 1, 1, 3, 5, 11}) // {1, 2}
for (; x; x &= x - 1) "../number-theory/ModPow.h" 40387d, 20 lines
sum += ft[x-1].query(ind(x-1, y)); }
return sum; void diff() { vector<ll> BerlekampMassey(vector<ll> s) {
} rep(i,1,sz(a)) a[i-1] = i*a[i]; int n = sz(s), L = 0, m = 0;
}; a.pop_back(); vector<ll> C(n), B(n), T;
} C[0] = B[0] = 1;
void divroot(double x0) {
double b = a.back(), c; a.back() = 0; ll b = 1;
RMQ.h for(int i=sz(a)-1; i--;) c = a[i], a[i] = a[i+1]*x0+b, b=c; rep(i,0,n) { ++m;
Description: Range Minimum Queries on an array. Returns min(V[a], V[a a.pop_back(); ll d = s[i] % mod;
+ 1], ... V[b - 1]) in constant time. } rep(j,1,L+1) d = (d + C[j] * s[i - j]) % mod;
Usage: RMQ rmq(values); }; if (!d) continue;
rmq.query(inclusive, exclusive); T = C; ll coef = d * modpow(b, mod-2) % mod;
Time: O (|V | log |V | + Q) 1f8996, 19 lines rep(j,m,n) C[j] = (C[j] - coef * B[j - m]) % mod;
template<class T> PolyRoots.h if (2 * L > i) continue;
struct RMQ { Description: Finds the real roots to a polynomial. L = i + 1 - L; B = T; b = d; m = 0;
vector<vector<T>> jmp; Usage: poly roots({{2,-3,1}},-1e9,1e9) // solve xˆ2-3x+2 = 0 }
Time: O n2 log(1/)
For hashing use 970592641 (31-bit number), 31443539979727 D(n) = (n−1)(D(n−1)+D(n−2)) = nD(n−1)+(−1)n = n! llllmultinomial(vi& v) {
c = 1, m = v.empty() ? 1 : v[0];
(45-bit), 3006703054056749 (52-bit). There are 78498 primes e rep(i,1,sz(v)) rep(j,0,v[i])
c = c * ++m / (j+1);
less than 1 000 000. return c;
6.1.4 Burnside’s lemma }
Primitive roots exist modulo any prime power pa , except for Given a group G of symmetries and a set X, the number of
p = 2, a > 2, and there are φ(φ(pa )) many. For p = 2, a > 2, elements of X up to symmetry equals 6.3 General purpose numbers
the group Z× 2a is instead isomorphic to Z2 × Z2a−2 .
1 X
|X g |, 6.3.1 Stirling numbers of the first kind
|G|
g∈G
5.8 Estimates Number of permutations on n items with k cycles.
where X g are the elements fixed by g (g.x = x).
P
If f (n) counts “configurations” (of some sort) of length n, we c(n, k) = c(n − 1, k − 1) + (n − 1)c(n − 1, k), c(0, 0) = 1
d|n d = O(n log log n). Pn
can ignore rotational symmetry using G = Zn to get k
k=0 c(n, k)x = x(x + 1) . . . (x + n − 1)
The number of divisors of n is at most around 100 for n−1
n < 5e4, 500 for n < 1e7, 2000 for n < 1e10, 200 000 for 1X 1X c(8, k) = 8, 0, 5040, 13068, 13132, 6769, 1960, 322, 28, 1
g(n) = f (gcd(n, k)) = f (k)φ(n/k).
n < 1e19. n n c(n, 2) = 0, 0, 1, 3, 11, 50, 274, 1764, 13068, 109584, . . .
k=0 k|n
KTH BellmanFord FloydWarshall TopoSort EulerWalk PushRelabel 11
6.3.2 Eulerian numbers Graph (7) rep(i,0,n) if (indeg[i] == 0) q.push(-i);
int nr = 0;
Number of permutations π ∈ Sn in which exactly k elements 7.1 Fundamentals while (q.size() > 0) {
int i = -q.front(); // top () for priority queue
are greater than the previous element. k j:s s.t. idx[i] = nr++;
π(j) > π(j + 1), k + 1 j:s s.t. π(j) ≥ j, k j:s s.t. BellmanFord.h q.pop();
Description: Calculates shortest paths from s in a graph that might have trav(e, edges[i])
π(j) > j. negative edge weights. Unreachable nodes get dist = inf; nodes reachable if (--indeg[e] == 0) q.push(-e);
through negative-weight cycles get dist = -inf. Assumes V 2 max |wi | < ∼263 . }
return nr == n;
E(n, k) = (n − k)E(n − 1, k − 1) + (k + 1)E(n − 1, k) Time: O (V E) 53f20b, 23 lines }
const ll inf = LLONG_MAX;
E(n, 0) = E(n, n − 1) = 1 struct Ed { int a, b, w, s() { return a < b ? a : -a; }};
k
struct Node { ll dist = inf; int prev = -1; }; 7.2 Euler walk
X n+1 void bellmanFord(vector<Node>& nodes, vector<Ed>& eds, int s) {
E(n, k) = (−1)j (k + 1 − j)n nodes[s].dist = 0; EulerWalk.h
j=0
j sort(all(eds), [](Ed a, Ed b) { return a.s() < b.s(); }); Description: Eulerian undirected/directed path/cycle algorithm. Returns
a list of nodes in the Eulerian path/cycle with src at both start and end,
int lim = sz(nodes) / 2 + 2; // /3+100 with shuffled vertices or empty list if no cycle/path exists. To get edge indices back, also put
6.3.3 Stirling numbers of the second kind rep(i,0,lim) trav(ed, eds) { it->second in s (and then ret).
Node cur = nodes[ed.a], &dest = nodes[ed.b]; Time: O (E) where E is the number of edges. f8bd47, 27 lines
Partitions of n distinct elements into exactly k if (abs(cur.dist) == inf) continue;
struct V {
ll d = cur.dist + ed.w;
groups. if (d < dest.dist) { vector<pii> outs; // ( dest , edge index )
dest.prev = ed.a; int nins = 0;
};
S(n, k) = S(n − 1, k − 1) + kS(n − 1, k) dest.dist = (i < lim-1 ? d : -inf);
}
} vi euler_walk(vector<V>& nodes, int nedges, int src=0) {
int c = 0;
S(n, 1) = S(n, n) = 1 rep(i,0,lim) trav(e, eds) {
trav(n, nodes) c += abs(n.nins - sz(n.outs));
if (nodes[e.a].dist == -inf)
k nodes[e.b].dist = -inf; if (c > 2) return {};
1 X k−j k vector<vector<pii>::iterator> its;
S(n, k) = (−1) jn }
trav(n, nodes)
k! j=0 j }
its.push_back(n.outs.begin());
vector<bool> eu(nedges);
FloydWarshall.h vi ret, s = {src};
6.3.4 Bell numbers Description: Calculates all-pairs shortest path in a directed graph that while(!s.empty()) {
might have negative edge weights. Input is an distance matrix m, where int x = s.back();
Total number of partitions of n distinct elements. B(n) = m[i][j] = inf if i and j are not adjacent. As output, m[i][j] is set to the auto& it = its[x], end = nodes[x].outs.end();
shortest distance between i and j, inf if no path, or -inf if the path goes while(it != end && eu[it->second]) ++it;
1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, . . . . For p prime, through a negative-weight cycle. if(it == end) { ret.push_back(x); s.pop_back(); }
Time: O N 3
else { s.push_back(it->first); eu[it->second] = true; }
531245, 12 lines
B(pm + n) ≡ mB(n) + B(n + 1) (mod p) const ll inf = 1LL << 62;
}
if(sz(ret) != nedges+1)
void floydWarshall(vector<vector<ll>>& m) { ret.clear(); // No Eulerian cycles/paths .
int n = sz(m); // else , non−cycle i f ret . front () != ret . back ()
6.3.5 Catalan numbers rep(i,0,n) m[i][i] = min(m[i][i], 0LL); reverse(all(ret));
rep(k,0,n) rep(i,0,n) rep(j,0,n) return ret;
if (m[i][k] != inf && m[k][j] != inf) { }
auto newDist = max(m[i][k] + m[k][j], -inf);
1 2n 2n 2n (2n)! m[i][j] = min(m[i][j], newDist);
Cn = = − = }
n+1 n n n+1 (n + 1)!n! rep(k,0,n) if (m[k][k] < 0) rep(i,0,n) rep(j,0,n) 7.3 Network flow
if (m[i][k] != inf && m[k][j] != inf) m[i][j] = -inf;
2(2n + 1) X
C0 = 1, Cn+1 = Cn , Cn+1 = Ci Cn−i } PushRelabel.h
n+2 Description: Push-relabel using the highest label selection rule and the gap
TopoSort.h heuristic. Quite fast in practice. To obtain the actual flow, look at positive
Cn = 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, . . . Description: Topological sorting. Given is an oriented graph. Output is an values only.
√
ordering of vertices (array idx), such that there are edges only from left to Time: O V 2 E
• sub-diagonal monotone paths in an n × n grid. right. The function returns false if there is a cycle in the graph.
6c4045, 49 lines
typedef ll Flow;
• strings with n pairs of parenthesis, correctly nested. Time: O (|V | + |E|) 0582b8, 18 lines struct Edge {
• binary trees with with n + 1 leaves (0 or 2 children). template<class E, class I> int dest, back;
bool topo_sort(const E &edges, I &idx, int n) { Flow f, c;
• ordered trees with n + 1 vertices. vi indeg(n); };
• ways a convex polygon with n + 2 sides can be cut into rep(i,0,n)
trav(e, edges[i]) struct PushRelabel {
triangles by connecting vertices with straight lines. indeg[e]++; vector<vector<Edge>> g;
• permutations of [n] with no 3-term increasing subseq. queue<int> q; // use priority queue for l e x i c . smallest ans . vector<Flow> ec;
KTH MinCostMaxFlow EdmondsKarp MinCut GlobalMinCut 12
vector<Edge*> cur; red[to].push_back(from); T flow = 0;
vector<vi> hs; vi H; } vi par(sz(graph)), q = par;
PushRelabel(int n) : g(n), ec(n), cur(n), hs(2*n), H(n) {}
void path(int s) { for (;;) {
void add_edge(int s, int t, Flow cap, Flow rcap=0) { fill(all(seen), 0); fill(all(par), -1);
if (s == t) return; fill(all(dist), INF); par[source] = 0;
g[s].push_back({t, sz(g[t]), 0, cap}); dist[s] = 0; ll di; int ptr = 1;
g[t].push_back({s, sz(g[s])-1, 0, rcap}); q[0] = source;
} __gnu_pbds::priority_queue<pair<ll, int>> q;
vector<decltype(q)::point_iterator> its(N); rep(i,0,ptr) {
void add_flow(Edge& e, Flow f) { q.push({0, s}); int x = q[i];
Edge &back = g[e.dest][e.back]; trav(e, graph[x]) {
if (!ec[e.dest] && f) hs[H[e.dest]].push_back(e.dest); auto relax = [&](int i, ll cap, ll cost, int dir) { if (par[e.first] == -1 && e.second > 0) {
e.f += f; e.c -= f; ec[e.dest] += f; ll val = di - pi[i] + cost; par[e.first] = x;
back.f -= f; back.c += f; ec[back.dest] -= f; if (cap && val < dist[i]) { q[ptr++] = e.first;
} dist[i] = val; if (e.first == sink) goto out;
Flow maxflow(int s, int t) { par[i] = {s, dir}; }
int v = sz(g); H[s] = v; ec[t] = 1; if (its[i] == q.end()) its[i] = q.push({-dist[i], i}); }
vi co(2*v); co[0] = v-1; else q.modify(its[i], {-dist[i], i}); }
rep(i,0,v) cur[i] = g[i].data(); } return flow;
trav(e, g[s]) add_flow(e, e.c); }; out:
T inc = numeric_limits<T>::max();
for (int hi = 0;;) { while (!q.empty()) { for (int y = sink; y != source; y = par[y])
while (hs[hi].empty()) if (!hi--) return -ec[s]; s = q.top().second; q.pop(); inc = min(inc, graph[par[y]][y]);
int u = hs[hi].back(); hs[hi].pop_back(); seen[s] = 1; di = dist[s] + pi[s];
while (ec[u] > 0) // discharge u trav(i, ed[s]) if (!seen[i]) flow += inc;
if (cur[u] == g[u].data() + sz(g[u])) { relax(i, cap[s][i] - flow[s][i], cost[s][i], 1); for (int y = sink; y != source; y = par[y]) {
H[u] = 1e9; trav(i, red[s]) if (!seen[i]) int p = par[y];
trav(e, g[u]) if (e.c && H[u] > H[e.dest]+1) relax(i, flow[i][s], -cost[i][s], 0); if ((graph[p][y] -= inc) <= 0) graph[p].erase(y);
H[u] = H[e.dest]+1, cur[u] = &e; } graph[y][p] += inc;
if (++co[H[u]], !--co[hi] && hi < v) rep(i,0,N) pi[i] = min(pi[i] + dist[i], INF); }
rep(i,0,v) if (hi < H[i] && H[i] < v) } }
--co[H[i]], H[i] = v + 1; }
hi = H[u]; pair<ll, ll> maxflow(int s, int t) {
} else if (cur[u]->c && H[u] == H[cur[u]->dest]+1) ll totflow = 0, totcost = 0;
add_flow(*cur[u], min(ec[u], cur[u]->c)); while (path(s), seen[t]) { MinCut.h
else ++cur[u]; ll fl = INF; Description: After running max-flow, the left side of a min-cut from s to t
} for (int p,r,x = t; tie(p,r) = par[x], x != s; x = p) is given by all vertices reachable from s, only traversing edges with positive
} fl = min(fl, r ? cap[p][x] - flow[p][x] : flow[x][p]); residual capacity.
}; totflow += fl;
for (int p,r,x = t; tie(p,r) = par[x], x != s; x = p)
if (r) flow[p][x] += fl;
MinCostMaxFlow.h else flow[x][p] -= fl; GlobalMinCut.h
Description: Min-cost max-flow. cap[i][j] != cap[j][i] is allowed; double } Description: Find a global minimum cut in an undirected graph, as repre-
edges are not. If costs can be negative, call setpi before maxflow, but note rep(i,0,N) rep(j,0,N) totcost += cost[i][j] * flow[i][j]; sented by an adjacency matrix.
Time: O V 3
that negative cost cycles are not supported. To obtain the actual flow, look return {totflow, totcost}; 03261f, 31 lines
at positive values only. }
Time: Approximately O E 2
pair<int, vi> GetMinCut(vector<vi>& weights) {
6915ce, 81 lines int N = sz(weights);
// I f some costs can be negative , c a l l t h i s before maxflow :
#include <bits/extc++.h> vi used(N), cut, best_cut;
void setpi(int s) { // ( otherwise , leave t h i s out)
int best_weight = -1;
fill(all(pi), INF); pi[s] = 0;
const ll INF = numeric_limits<ll>::max() / 4;
int it = N, ch = 1; ll v;
typedef vector<ll> VL; for (int phase = N-1; phase >= 0; phase--) {
while (ch-- && it--)
vi w = weights[0], added = used;
rep(i,0,N) if (pi[i] != INF)
struct MCMF { int prev, k = 0;
trav(to, ed[i]) if (cap[i][to])
int N; rep(i,0,phase){
if ((v = pi[i] + cost[i][to]) < pi[to])
vector<vi> ed, red; prev = k;
pi[to] = v, ch = 1;
vector<VL> cap, flow, cost; k = -1;
assert(it >= 0); // negative cost cycle
vi seen; rep(j,1,N)
}
VL dist, pi; if (!added[j] && (k == -1 || w[j] > w[k])) k = j;
};
vector<pii> par; if (i == phase-1) {
rep(j,0,N) weights[prev][j] += weights[k][j];
MCMF(int N) : EdmondsKarp.h rep(j,0,N) weights[j][prev] = weights[prev][j];
N(N), ed(N), red(N), cap(N, VL(N)), flow(cap), cost(cap), Description: Flow algorithm with guaranteed complexity O(V E 2 ). To get used[k] = true;
seen(N), dist(N), pi(N), par(N) {} edge flow values, compare capacities before and after, and take the positive cut.push_back(k);
values only. if (best_weight == -1 || w[k] < best_weight) {
void addEdge(int from, int to, ll cap, ll cost) { 979bb9, 35 lines best_cut = cut;
this->cap[from][to] = cap; template<class T> T edmondsKarp(vector<unordered_map<int, T>>& best_weight = w[k];
this->cost[from][to] = cost; graph, int source, int sink) { }
ed[from].push_back(to); assert(source != sink); } else {
KTH hopcroftKarp DFSMatching MinimumVertexCover WeightedMatching GeneralMatching 13
rep(j,0,N) Usage: vi btoa(m, -1); dfsMatching(g, btoa); v[j] = cost[0][j] - u[0];
w[j] += weights[k][j]; Time: O (V E) 6a3472, 22 lines
rep(i,1,n) v[j] = min(v[j], cost[i][j] - u[i]);
added[k] = true; }
} bool find(int j, vector<vi>& g, vi& btoa, vi& vis) {
} if (btoa[j] == -1) return 1; L = R = vi(n, -1);
} vis[j] = 1; int di = btoa[j]; rep(i,0,n) rep(j,0,n) {
return {best_weight, best_cut}; trav(e, g[di]) if (R[j] != -1) continue;
} if (!vis[e] && find(e, g, btoa, vis)) { if (zero(cost[i][j] - u[i] - v[j])) {
btoa[e] = di; L[i] = j;
return 1; R[j] = i;
}
7.4 Matching return 0;
mated++;
break;
} }
hopcroftKarp.h int dfsMatching(vector<vi>& g, vi& btoa) { }
Description: Fast bipartite matching algorithm. Graph g should be a list vi vis;
of neighbors of the left partition, and btoa should be a vector full of -1’s of rep(i,0,sz(g)) { for (; mated < n; mated++) { // u n t i l solution i s f e a s i b l e
the same size as the right partition. Returns the size of the matching. btoa[i] vis.assign(sz(btoa), 0); int s = 0;
will be the match for vertex i on the right side, or −1 if it’s not matched. trav(j,g[i]) while (L[s] != -1) s++;
Usage: vi btoa(m, -1); hopcroftKarp(g, btoa); if (find(j, g, btoa, vis)) { fill(all(dad), -1);
√
btoa[j] = i;
Time: O VE fill(all(seen), 0);
536939, 42 lines break; rep(k,0,n)
bool dfs(int a, int L, vector<vi>& g, vi& btoa, vi& A, vi& B) { } dist[k] = cost[s][k] - u[s] - v[k];
if (A[a] != L) return 0; }
A[a] = -1; return sz(btoa) - (int)count(all(btoa), -1); int j = 0;
trav(b, g[a]) if (B[b] == L + 1) { } for (;;) {
B[b] = 0; j = -1;
if (btoa[b] == -1 || dfs(btoa[b], L + 1, g, btoa, A, B)) rep(k,0,n){
return btoa[b] = a, 1; MinimumVertexCover.h if (seen[k]) continue;
} Description: Finds a minimum vertex cover in a bipartite graph. The size if (j == -1 || dist[k] < dist[j]) j = k;
return 0; is the same as the size of a maximum matching, and the complement is a }
} maximum independent set. seen[j] = 1;
"DFSMatching.h" d0b3f2, 20 lines
int i = R[j];
int hopcroftKarp(vector<vi>& g, vi& btoa) { vi cover(vector<vi>& g, int n, int m) { if (i == -1) break;
int res = 0; vi match(m, -1); rep(k,0,n) {
vi A(g.size()), B(btoa.size()), cur, next; int res = dfsMatching(g, match); if (seen[k]) continue;
for (;;) { vector<bool> lfound(n, true), seen(m); auto new_dist = dist[j] + cost[i][k] - u[i] - v[k];
fill(all(A), 0); trav(it, match) if (it != -1) lfound[it] = false; if (dist[k] > new_dist) {
fill(all(B), 0); vi q, cover; dist[k] = new_dist;
cur.clear(); rep(i,0,n) if (lfound[i]) q.push_back(i); dad[k] = j;
trav(a, btoa) if(a != -1) A[a] = -1; while (!q.empty()) { }
rep(a,0,sz(g)) if(A[a] == 0) cur.push_back(a); int i = q.back(); q.pop_back(); }
for (int lay = 1;; lay++) { lfound[i] = 1; }
bool islast = 0; trav(e, g[i]) if (!seen[e] && match[e] != -1) {
next.clear(); seen[e] = true; rep(k,0,n) {
trav(a, cur) trav(b, g[a]) { q.push_back(match[e]); if (k == j || !seen[k]) continue;
if (btoa[b] == -1) { } auto w = dist[k] - dist[j];
B[b] = lay; } v[k] += w, u[R[k]] -= w;
islast = 1; rep(i,0,n) if (!lfound[i]) cover.push_back(i); }
} rep(i,0,m) if (seen[i]) cover.push_back(n+i); u[s] += dist[j];
else if (btoa[b] != a && !B[b]) { assert(sz(cover) == res);
B[b] = lay; return cover; while (dad[j] >= 0) {
next.push_back(btoa[b]); } int d = dad[j];
} R[j] = R[d];
} L[R[j]] = j;
if (islast) break; WeightedMatching.h j = d;
if (next.empty()) return res; Description: Min cost bipartite matching. Negate costs for max cost. }
trav(a, next) A[a] = lay; Time: O N 3 055ca9, 75 lines R[j] = s;
cur.swap(next); L[s] = j;
} typedef vector<double> vd;
}
rep(a,0,sz(g)) bool zero(double x) { return fabs(x) < 1e-10; }
auto value = vd(1)[0];
res += dfs(a, 0, g, btoa, A, B); double MinCostMatching(const vector<vd>& cost, vi& L, vi& R) {
rep(i,0,n) value += cost[i][L[i]];
} int n = sz(cost), mated = 0;
return value;
} vd dist(n), u(n), v(n);
}
vi dad(n), seen(n);
DFSMatching.h rep(i,0,n) {
GeneralMatching.h
Description: Simple bipartite matching algorithm. Graph g should be a list u[i] = cost[i][0];
Description: Matching for general graphs. Fails with probability N/mod.
of neighbors of the left partition, and btoa should be a vector full of -1’s of rep(j,1,n) u[i] = min(u[i], cost[i][j]);
Time: O N 3
the same size as the right partition. Returns the size of the matching. btoa[i] }
"../numerical/MatrixInverse-mod.h" bb8be4, 40 lines
will be the match for vertex i on the right side, or −1 if it’s not matched. rep(j,0,n) {
KTH SCC BiconnectedComponents 2sat MaximalCliques 14
vector<pii> generalMatching(int N, vector<pii>& ed) { } Time: O (N + E), where N is the number of boolean variables, and E is the
vector<vector<ll>> mat(N, vector<ll>(N)), A; return val[j] = low; number of clauses. 0911c1, 56 lines
trav(pa, ed) { }
int a = pa.first, b = pa.second, r = rand() % mod; template<class G, class F> void scc(G& g, F f) { struct TwoSat {
mat[a][b] = r, mat[b][a] = (mod - r) % mod; int n = sz(g); int N;
} val.assign(n, 0); comp.assign(n, -1); vector<vi> gr;
Time = ncomps = 0; vi values; // 0 = false , 1 = true
int r = matInv(A = mat), M = 2*N - r, fi, fj; rep(i,0,n) if (comp[i] < 0) dfs(i, g, f);
assert(r % 2 == 0); } TwoSat(int n = 0) : N(n), gr(2*n) {}
e res p
distance eps from the line. P is supposed to be Point<T> where T is e.g. pair<Angle, Angle> segmentAngles(Angle a, Angle b) {
SegmentDistance.h double or long long. It uses products in intermediate steps so watch out for if (b < a) swap(a, b);
Description: overflow if using int or long long. return (b < a.t180() ?
Returns the shortest distance between point p and the line make_pair(a, b) : make_pair(b, a.t360()));
Usage: bool left = sideOf(p1,p2,q)==1;
segment from point s to e. s }
"Point.h" 3af81c, 9 lines
Usage: Point<double> a, b(2,2), p(1,1); Angle operator+(Angle a, Angle b) { // point a + vector b
bool onSegment = segDist(a,b,p) < 1e-10; template<class P>
Angle r(a.x + b.x, a.y + b.y, a.t);
"Point.h" 5c88f4, 6 lines 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;
template<class P>
double segDist(P& s, P& e, P& p) { }
int sideOf(const P& s, const P& e, const P& p, double eps) {
if (s==e) return (p-s).dist(); Angle angleDiff(Angle a, Angle b) { // angle b − angle a
auto a = (e-s).cross(p-s);
auto d = (e-s).dist2(), t = min(d,max(.0,(p-s).dot(e-s))); int tu = b.t - a.t; a.t = b.t;
double l = (e-s).dist()*eps;
return ((p-s)*d-(e-s)*t).dist()/d; 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);
} }
}
KTH CircleIntersection circleTangents circumcircle MinimumEnclosingCircle InsidePolygon PolygonArea PolygonCenter PolygonCut ConvexHull HullDiameter PointInsideHull 18
8.2 Circles rep(k,0,j) if ((o - ps[k]).dist() > r * EPS) { vector<P> res;
o = ccCenter(ps[i], ps[j], ps[k]); rep(i,0,sz(poly)) {
r = (o - ps[i]).dist(); P cur = poly[i], prev = i ? poly[i-1] : poly.back();
CircleIntersection.h } bool side = s.cross(e, cur) < 0;
Description: Computes the pair of points at which two circles intersect. } if (side != (s.cross(e, prev) < 0))
Returns false in case of no intersection. } res.push_back(lineInter(s, e, cur, prev).second);
"Point.h" 84d6d3, 11 lines
return {o, r}; if (side)
typedef Point<double> P; } res.push_back(cur);
bool circleInter(P a,P b,double r1,double r2,pair<P, P>* out) { }
if (a == b) { assert(r1 != r2); return false; } return res;
P vec = b - a;
double d2 = vec.dist2(), sum = r1+r2, dif = r1-r2,
8.3 Polygons }
pair<P, double> mec(vector<P> ps) { PolygonCut.h e bool inHull(const vector<P>& l, P p, bool strict = true) {
shuffle(all(ps), mt19937(time(0))); Description: int a = 1, b = sz(l) - 1, r = !strict;
P o = ps[0]; Returns a vector with the vertices of a polygon with every- if (sz(l) < 3) return r && onSegment(l[0], l.back(), p);
double r = 0, EPS = 1 + 1e-8; thing to the left of the line going from s to e cut away. if (sideOf(l[0], l[a], l[b]) > 0) swap(a, b);
rep(i,0,sz(ps)) if ((o - ps[i]).dist() > r * EPS) { Usage: vector<P> p = ...; s if (sideOf(l[0], l[a], p) >= r || sideOf(l[0], l[b], p)<= -r)
o = ps[i], r = 0; p = polygonCut(p, P(0,0), P(1,0)); return false;
rep(j,0,i) if ((o - ps[j]).dist() > r * EPS) { "Point.h", "lineIntersection.h" f2b7d4, 13 lines while (abs(a - b) > 1) {
o = (ps[i] + ps[j]) / 2; typedef Point<double> P; int c = (a + b) / 2;
r = (o - ps[i]).dist(); vector<P> polygonCut(const vector<P>& poly, P s, P e) { (sideOf(l[0], l[c], p) > 0 ? b : a) = c;
KTH LineHullIntersection ClosestPair kdTree FastDelaunay 19
} int j = 0; if (bsec < best.first)
return sgn(l[a].cross(l[b], p)) < r; trav(p, v) { best = min(best, search(s, p));
} P d{1 + (ll)sqrt(ret.first), 0}; return best;
while (v[j].y <= p.y - d.x) S.erase(v[j++]); }
auto lo = S.lower_bound(p - d), hi = S.upper_bound(p + d);
LineHullIntersection.h for (; lo != hi; ++lo) // find nearest point to a point , and i t s squared distance
Description: Line-convex polygon intersection. The polygon must be ccw
ret = min(ret, {(*lo - p).dist2(), {*lo, p}}); // ( requires an arbitrary operator< for Point)
and have no colinear points. lineHull(line, poly) returns a pair describing the
S.insert(p); pair<T, P> nearest(const P& p) {
intersection of a line with the polygon: • (−1, −1) if no collision, • (i, −1) if
} return search(root, p);
touching the corner i, • (i, i) if along side (i, i + 1), • (i, j) if crossing sides
return ret.second; }
(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
the line hits the polygon. extrVertex returns the point of a hull with the
max projection onto a line.
Time: O (N + Q log n) kdTree.h FastDelaunay.h
"Point.h" 758f22, 39 lines Description: KD-tree (2d, can be extended to 3d) Description: Fast Delaunay triangulation. Each circumcircle contains none
"Point.h" bac5b0, 63 lines of the input points. There must be no duplicate points. If all points are on a
typedef array<P, 2> Line;
typedef long long T; line, no triangles will be returned. Should work for doubles as well, though
#define cmp(i,j) sgn(dir.perp().cross(poly[(i)%n]-poly[(j)%n]))
typedef Point<T> P; there may be precision issues in ’circ’. Returns triangles in order {t[0][0],
#define extr(i) cmp(i + 1, i) >= 0 && cmp(i, i - 1 + n) < 0
const T INF = numeric_limits<T>::max(); t[0][1], t[0][2], t[1][0], . . . }, all counter-clockwise.
int extrVertex(vector<P>& poly, P dir) {
Time: O (n log n)
int n = sz(poly), lo = 0, hi = n;
bool on_x(const P& a, const P& b) { return a.x < b.x; } "Point.h" bf87ec, 88 lines
if (extr(0)) return 0;
while (lo + 1 < hi) { bool on_y(const P& a, const P& b) { return a.y < b.y; } typedef Point<ll> P;
int m = (lo + hi) / 2; typedef struct Quad* Q;
if (extr(m)) return m; struct Node { typedef __int128_t lll; // (can be l l i f coords are < 2e4)
int ls = cmp(lo + 1, lo), ms = cmp(m + 1, m); P pt; // i f t h i s i s a leaf , the single point in i t P arb(LLONG_MAX,LLONG_MAX); // not equal to any other point
(ls < ms || (ls == ms && ls == cmp(lo, m)) ? hi : lo) = m; T x0 = INF, x1 = -INF, y0 = INF, y1 = -INF; // bounds
} Node *first = 0, *second = 0; struct Quad {
return lo; bool mark; Q o, rot; P p;
} T distance(const P& p) { // min squared distance to a point P F() { return r()->p; }
T x = (p.x < x0 ? x0 : p.x > x1 ? x1 : p.x); Q r() { return rot->rot; }
#define cmpL(i) sgn(line[0].cross(poly[i], line[1])) T y = (p.y < y0 ? y0 : p.y > y1 ? y1 : p.y); Q prev() { return rot->o->rot; }
array<int, 2> lineHull(Line line, vector<P> poly) { return (P(x,y) - p).dist2(); Q next() { return r()->prev(); }
int endA = extrVertex(poly, (line[0] - line[1]).perp()); } };
int endB = extrVertex(poly, (line[1] - line[0]).perp());
if (cmpL(endA) < 0 || cmpL(endB) > 0) Node(vector<P>&& vp) : pt(vp[0]) { bool circ(P p, P a, P b, P c) { // i s p in the circumcircle?
return {-1, -1}; for (P p : vp) { lll p2 = p.dist2(), A = a.dist2()-p2,
array<int, 2> res; x0 = min(x0, p.x); x1 = max(x1, p.x); B = b.dist2()-p2, C = c.dist2()-p2;
rep(i,0,2) { y0 = min(y0, p.y); y1 = max(y1, p.y); return p.cross(a,b)*C + p.cross(b,c)*A + p.cross(c,a)*B > 0;
int lo = endB, hi = endA, n = sz(poly); } }
while ((lo + 1) % n != hi) { if (vp.size() > 1) { Q makeEdge(P orig, P dest) {
int m = ((lo + hi + (lo < hi ? 0 : n)) / 2) % n; // s p l i t on x i f the box i s wider than high (not best Q q[] = {new Quad{0,0,0,orig}, new Quad{0,0,0,arb},
(cmpL(m) == cmpL(endB) ? lo : hi) = m; heuristic . . . ) new Quad{0,0,0,dest}, new Quad{0,0,0,arb}};
} sort(all(vp), x1 - x0 >= y1 - y0 ? on_x : on_y); rep(i,0,4)
res[i] = (lo + !cmpL(hi)) % n; // divide by taking h a l f the array for each child (not q[i]->o = q[-i & 3], q[i]->rot = q[(i+1) & 3];
swap(endA, endB); // best performance with many duplicates in the middle) return *q;
} int half = sz(vp)/2; }
if (res[0] == res[1]) return {res[0], -1}; first = new Node({vp.begin(), vp.begin() + half}); void splice(Q a, Q b) {
if (!cmpL(res[0]) && !cmpL(res[1])) second = new Node({vp.begin() + half, vp.end()}); swap(a->o->rot->o, b->o->rot->o); swap(a->o, b->o);
switch ((res[0] - res[1] + sz(poly) + 1) % sz(poly)) { } }
case 0: return {res[0], res[0]}; } Q connect(Q a, Q b) {
case 2: return {res[1], res[1]}; }; Q q = makeEdge(a->F(), b->p);
} splice(q, a->next());
return res; struct KDTree { splice(q->r(), b);
} Node* root; return q;
KDTree(const vector<P>& vp) : root(new Node({all(vp)})) {} }
8.4 Misc. Point Set Problems pair<T, P> search(Node *node, const P& p) {
if (!node->first) {
pair<Q,Q> rec(const vector<P>& s) {
if (sz(s) <= 3) {
// uncomment i f we should not find the point i t s e l f : Q a = makeEdge(s[0], s[1]), b = makeEdge(s[1], s.back());
ClosestPair.h // i f (p == node−>pt ) return {INF, P() }; if (sz(s) == 2) return { a, a->r() };
Description: Finds the closest pair of points. return make_pair((p - node->pt).dist2(), node->pt); splice(a->r(), b);
Time: O (n log n) } auto side = s[0].cross(s[1], s[2]);
"Point.h" d31bbf, 17 lines Q c = side ? connect(b, a) : 0;
typedef Point<ll> P; Node *f = node->first, *s = node->second; return {side < 0 ? c->r() : a, side < 0 ? c : b->r() };
pair<P, P> closest(vector<P> v) { T bfirst = f->distance(p), bsec = s->distance(p); }
assert(sz(v) > 1); if (bfirst > bsec) swap(bsec, bfirst), swap(f, s);
set<P> S; #define H(e) e->F(), e->p
sort(all(v), [](P a, P b) { return a.y < b.y; }); // search c l o s e s t side f i r s t , other side i f needed #define valid(e) (e->F().cross(H(base)) > 0)
pair<ll, pair<P, P>> ret{LLONG_MAX, {P(), P()}}; auto best = search(f, p); Q A, B, ra, rb;
KTH PolyhedronVolume Point3D 3dHull sphericalDistance KMP Zfunc 20
int half = sz(s) / 2; P operator-(R p) const { return P(x-p.x, y-p.y, z-p.z); } rep(j,0,nw) {
tie(ra, A) = rec({all(s) - half}); P operator*(T d) const { return P(x*d, y*d, z*d); } F f = FS[j];
tie(B, rb) = rec({sz(s) - half + all(s)}); 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);
while ((B->p.cross(H(A)) < 0 && (A = A->next())) || T dot(R p) const { return x*p.x + y*p.y + z*p.z; } C(a, b, c); C(a, c, b); C(b, c, a);
(A->p.cross(H(B)) > 0 && (B = B->r()->o))); P cross(R p) const { }
Q base = connect(B->r(), A); return P(y*p.z - z*p.y, z*p.x - x*p.z, x*p.y - y*p.x); }
if (A->p == ra->p) ra = base->r(); } trav(it, FS) if ((A[it.b] - A[it.a]).cross(
if (B->p == rb->p) rb = base; T dist2() const { return x*x + y*y + z*z; } A[it.c] - A[it.a]).dot(it.q) <= 0) swap(it.c, it.b);
double dist() const { return sqrt((double)dist2()); } return FS;
#define DEL(e, init, dir) Q e = init->dir; if (valid(e)) \ //Azimuthal angle ( longitude ) to x−axis in interval [−pi , pi ] };
while (circ(e->dir->F(), H(base), e->F())) { \ double phi() const { return atan2(y, x); }
Q t = e->dir; \ //Zenith angle ( l a t i t u d e ) to the z−axis in interval [0 , pi ]
splice(e, e->prev()); \ double theta() const { return atan2(sqrt(x*x+y*y),z); }
sphericalDistance.h
Description: Returns the shortest distance on the sphere with radius ra-
splice(e->r(), e->r()->prev()); \ P unit() const { return *this/(T)dist(); } //makes d i s t ()=1
dius between the points with azimuthal angles (longitude) f1 (φ1 ) and f2 (φ2 )
e = t; \ //returns unit vector normal to ∗ t h i s and p
from x axis and zenith angles (latitude) t1 (θ1 ) and t2 (θ2 ) from z axis. All
} P normal(P p) const { return cross(p).unit(); }
angles measured in radians. The algorithm starts by converting the spheri-
for (;;) { //returns point rotated ’ angle ’ radians ccw around axis
cal coordinates to cartesian coordinates so if that is what you have you can
DEL(LC, base->r(), o); DEL(RC, base, prev()); P rotate(double angle, P axis) const {
use only the two last rows. dx*radius is then the difference between the
if (!valid(LC) && !valid(RC)) break; double s = sin(angle), c = cos(angle); P u = axis.unit();
two points in the x direction and d*radius is the total distance between the
if (!valid(LC) || (valid(RC) && circ(H(RC), H(LC)))) return u*dot(u)*(1-c) + (*this)*c - cross(u)*s;
points.
base = connect(RC, base->r()); } 611f07, 8 lines
else }; double sphericalDistance(double f1, double t1,
base = connect(base->r(), LC->r()); double f2, double t2, double radius) {
} double dx = sin(t2)*cos(f2) - sin(t1)*cos(f1);
return { ra, rb }; 3dHull.h double dy = sin(t2)*sin(f2) - sin(t1)*sin(f1);
} 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);
vector<P> triangulate(vector<P> pts) { faces will point return radius*2*asin(d/2);
outwards.
sort(all(pts)); assert(unique(all(pts)) == pts.end()); Time: O n2 }
if (sz(pts) < 2) return {}; "Point3D.h" c172e9, 49 lines
Q e = rec(pts).first;
typedef Point3D<double> P3;
vector<Q> q = {e};
int qi = 0;
Strings (9)
struct PR {
while (e->o->F().cross(e->F(), e->p) < 0) e = e->o;
#define ADD { Q c = e; do { c->mark = 1; pts.push_back(c->p); \
void ins(int x) { (a == -1 ? a : b) = x; } KMP.h
void rem(int x) { (a == x ? a : b) = -1; } Description: pi[x] computes the length of the longest prefix of s that ends
q.push_back(c->r()); c = c->next(); } while (c != e); }
int cnt() { return (a != -1) + (b != -1); } at x, other than s[0...x] itself (abacaba -> 0010123). Can be used to find all
ADD; pts.clear();
int a, b; occurrences of a string.
while (qi < sz(q)) if (!(e = q[qi++])->mark) ADD;
}; Time: O (n)
return pts; d4375c, 16 lines
} vi pi(const string& s) {
struct F { P3 q; int a, b, c; };
vi p(sz(s));
vector<F> hull3d(const vector<P3>& A) { rep(i,1,sz(s)) {
8.5 3D 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];
PolyhedronVolume.h #define E(x,y) E[f.x][f.y] p[i] = g + (s[i] == s[g]);
Description: Magic formula for the volume of a polyhedron. Faces should vector<F> FS; }
point outwards. auto mf = [&](int i, int j, int k, int l) { return p;
1ec4d3, 6 lines }
P3 q = (A[j] - A[i]).cross((A[k] - A[i]));
template<class V, class L> if (q.dot(A[l]) > q.dot(A[i]))
double signed_poly_volume(const V& p, const L& trilist) { q = q * -1; vi match(const string& s, const string& pat) {
double v = 0; F f{q, i, j, k}; vi p = pi(pat + ’\0’ + s), res;
trav(i, trilist) v += p[i.a].cross(p[i.b]).dot(p[i.c]); E(a,b).ins(k); E(a,c).ins(j); E(b,c).ins(i); rep(i,sz(p)-sz(s),sz(p))
return v / 6; FS.push_back(f); if (p[i] == sz(pat)) res.push_back(i - 2 * sz(pat));
} }; return res;
rep(i,0,4) rep(j,i+1,4) rep(k,j+1,4) }
Point3D.h mf(i, j, k, 6 - i - j - k);
Description: Class to handle points in 3D space. T can be e.g. double or Zfunc.h
long long. rep(i,4,sz(A)) { Description: z[x] computes the length of the longest common prefix of s[i:]
8058ae, 32 lines rep(j,0,sz(FS)) { and s, except z[0] = 0. (abacaba -> 0010301)
template<class T> struct Point3D { F f = FS[j]; Time: O (n)
typedef Point3D P; if(f.q.dot(A[i]) > f.q.dot(A[f.a])) { 3ae526, 12 lines