├── Data structures ├── Centroid decomposition.cpp ├── Fenwick tree.cpp ├── Heavy light decomposition.cpp ├── Mo's.cpp ├── Order statistics.cpp ├── Persistent segment tree.cpp ├── Rmq.cpp ├── Sack.cpp ├── Sqrt Decomposition.cpp ├── Treap.cpp └── Treap2.0.cpp ├── Dp optimization ├── Convex hull trick dynamic.cpp ├── Convex hull trick.cpp ├── Divide and conquer.cpp └── Knuth.cpp ├── Formulas ├── 2-SAT rules.tex ├── Burnside's lemma.tex ├── Catalan Numbers.tex ├── Combinatorics.tex ├── Compound Interest.tex ├── DP optimization theory.tex ├── Euler Totient properties.tex ├── Fermat's theorem.tex ├── Great circle distance or geographical distance.tex ├── Heron's Formula.tex ├── Interesting theorems.tex ├── Law of sines and cosines.tex ├── Number of divisors.tex ├── Product of divisors of a number.tex ├── Pythagorean triples (a^2+ b^2=c^2).tex ├── Simplex Rules.tex ├── Sum of divisors of a number.tex ├── Summations.tex └── Theorems.tex ├── Geometry ├── 3D.cpp ├── General.cpp └── nonTested.cpp ├── Graphs ├── 2-satisfiability.cpp ├── Erdos–Gallai theorem.cpp ├── Eulerian path.cpp ├── Lowest common ancestor.cpp ├── Number of spanning trees.cpp ├── Scc.cpp ├── Tarjan tree.cpp ├── Tree binarization.cpp └── Yen.cpp ├── Math ├── Berlekamp-Massey.cpp ├── Chinese remainder theorem.cpp ├── Constant modular inverse.cpp ├── Extended euclides.cpp ├── Fast Fourier transform module.cpp ├── Fast fourier transform.cpp ├── Gauss jordan.cpp ├── Integral.tex ├── Lagrange Interpolation.cpp ├── Linear diophantine.cpp ├── Matrix multiplication.cpp ├── Miller rabin.cpp ├── Pollard's rho.cpp ├── Simplex.cpp ├── Simpson.cpp └── Totient and divisors.cpp ├── Network flows ├── Blossom.cpp ├── Dinic.cpp ├── Hopcroft karp.cpp ├── Maximum bipartite matching.cpp ├── Maximum flow minimum cost.cpp ├── Stoer Wagner.cpp └── Weighted matching.cpp ├── Strings ├── Aho corasick.cpp ├── Hashing.cpp ├── Kmp automaton.cpp ├── Kmp.cpp ├── Manacher.cpp ├── Minimun expression.cpp ├── Suffix array.cpp ├── Suffix automaton.cpp └── Z algorithm.cpp ├── Utilities ├── Hash STL.cpp ├── Pragma optimizations.cpp ├── Random.cpp ├── template.cpp └── vimsrc.cpp └── cover.png /Data structures/Centroid decomposition.cpp: -------------------------------------------------------------------------------- 1 | namespace decomposition { 2 | int cnt[MAX], depth[MAX], f[MAX]; 3 | int dfs (int u, int p = -1) { 4 | cnt[u] = 1; 5 | for (int v : g[u]) 6 | if (!depth[v] && v != p) 7 | cnt[u] += dfs(v, u); 8 | return cnt[u]; 9 | } 10 | int get_centroid (int u, int r, int p = -1) { 11 | for (int v : g[u]) 12 | if (!depth[v] && v != p && cnt[v] > r) 13 | return get_centroid(v, r, u); 14 | return u; 15 | } 16 | int decompose (int u, int d = 1) { 17 | int centroid = get_centroid(u, dfs(u) >> 1); 18 | depth[centroid] = d; 19 | /// magic function 20 | for (int v : g[centroid]) 21 | if (!depth[v]) 22 | f[decompose(v, d + 1)] = centroid; 23 | return centroid; 24 | } 25 | int lca (int u, int v) { 26 | for (; u != v; u = f[u]) 27 | if (depth[v] > depth[u]) 28 | swap(u, v); 29 | return u; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Data structures/Fenwick tree.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: log(|N|) 2 | /// Tested: https://tinyurl.com/y88y7ws7 3 | int lower_find(int val) { /// last value < or <= to val 4 | int idx = 0; 5 | for(int i = 31-__builtin_clz(n); i >= 0; --i) { 6 | int nidx = idx | (1 << i); 7 | if(nidx <= n && bit[nidx] <= val) { /// change <= to < 8 | val -= bit[nidx]; 9 | idx = nidx; 10 | } 11 | } 12 | return idx; 13 | } 14 | -------------------------------------------------------------------------------- /Data structures/Heavy light decomposition.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/ybdbmbw7(problem L) 3 | int idx; 4 | vector len, depth, in, out, top, up; 5 | int dfs_len( int u, int p, int d ) { 6 | up[u] = p; depth[u] = d; 7 | int sz = 1; 8 | for( auto& v : g[u] ) { 9 | if( v == p ) continue; 10 | sz += dfs_len(v, u, d+1); 11 | if(len[ g[u][0] ] <= len[v]) swap(g[u][0], v); 12 | } 13 | return len[u] = sz; 14 | } 15 | void dfs_hld( int u, int p = 0 ) { 16 | in[u] = idx++; 17 | narr[in] = val[u]; /// to initialize the segment tree 18 | for( auto& v : g[u] ) { 19 | if( v == p ) continue; 20 | top[v] = (v == g[u][0] ? top[u] : v); 21 | dfs_hld(v, u); 22 | } 23 | out[u] = idx-1; 24 | } 25 | void update_hld( int u, int val ) { 26 | update_DS(in[u], val); 27 | } 28 | data query_hld( int u, int v ) { 29 | data val = NULL_DATA; 30 | while( top[u] != top[v] ) { 31 | if( depth[ top[u] ] < depth[ top[v] ] ) swap(u, v); 32 | val = val+query_DS(in[ top[u] ], in[u]); 33 | u = up[ top[u] ]; 34 | } 35 | if( depth[u] > depth[v] ) swap(u, v); 36 | val = val+query_DS(in[u], in[v]); 37 | return val; 38 | /// when updates are on edges use: 39 | /// if (depth[u] == depth[v]) return val; 40 | /// val = val+query_DS(hld_index[u] + 1, hld_index[v]); 41 | } 42 | void build(int n, int root) { 43 | top = len = in = out = up = depth = vector(n+1); 44 | idx = 1; /// DS index [1, n] 45 | dfs_len(root, root, 0); 46 | top[root] = root; 47 | dfs_hld(root, root); 48 | /// initialize DS 49 | } -------------------------------------------------------------------------------- /Data structures/Mo's.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N+Q|*sqrt(|N|)*|ADD/DEL|) 2 | /// Tested: Not yet 3 | // Requires add(), delete() and get_ans() 4 | struct query { 5 | int l, r, idx; 6 | query (int l, int r, int idx) : l(l), r(r), idx(idx) {} 7 | }; 8 | int S; // s = sqrt(n) 9 | bool cmp (query a, query b) { 10 | if (a.l/S != b.l/S) return a.l/S < b.l/S; 11 | return a.r > b.r; 12 | } 13 | S = sqrt(n); // n = size of array 14 | sort(q.begin(), q.end(), cmp); 15 | int l = 0, r = -1; 16 | for (int i = 0; i < q.size(); ++i) { 17 | while (r < q[i].r) add(++r); 18 | while (l > q[i].l) add(--l); 19 | while (r > q[i].r) del(r--); 20 | while (l < q[i].l) del(l++); 21 | ans[q[i].idx] = get_ans(); 22 | } 23 | -------------------------------------------------------------------------------- /Data structures/Order statistics.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace __gnu_pbds; 4 | typedef tree, rb_tree_tag, 5 | tree_order_statistics_node_update> ordered_set; 6 | //methods 7 | tree.find_by_order(k) //returns pointer to the k-th smallest element 8 | tree.order_of_key(x) //returns how many elements are smaller than x 9 | //if element does not exist 10 | tree.end() == tree.find_by_order(k) //true 11 | -------------------------------------------------------------------------------- /Data structures/Persistent segment tree.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log|N|) 2 | /// Tested: Not yet 3 | struct node { 4 | node *left, *right; 5 | int v; 6 | node() : left(this), right(this), v(0) {} 7 | node(node *left, node *right, int v) : 8 | left(left), right(right), v(v) {} 9 | node* update(int l, int r, int x, int value) { 10 | if (l == r) return new node(nullptr, nullptr, v + value); 11 | int m = (l + r) / 2; 12 | if (x <= m) 13 | return new node(left->update(l, m, x, value), right, v + value); 14 | return new node(left, right->update(m + 1, r, x, value), v + value); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /Data structures/Rmq.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log|N|) 2 | /// Tested: https://tinyurl.com/y739tcsj 3 | struct rmq { 4 | vector > table; 5 | rmq(vector &v) : table(v.size() + 1, vector(20)) { 6 | int n = v.size()+1; 7 | for (int i = 0; i < n; i++) table[i][0] = v[i]; 8 | for (int j = 1; (1< dis64(0, 1ll<<60); 5 | template 6 | class treap { 7 | private: 8 | struct item; 9 | typedef struct item * pitem; 10 | pitem root = NULL; 11 | struct item { 12 | ll prior; int cnt, rev; 13 | T key, add, fsum; 14 | pitem l, r; 15 | item(T x, ll p) { 16 | add = 0*x; key = fsum = x; 17 | cnt = 1; rev = 0; 18 | l = r = NULL; prior = p; 19 | } 20 | }; 21 | int cnt(pitem it) { return it ? it->cnt : 0; } 22 | void upd_cnt(pitem it) { 23 | if(it) it->cnt = cnt(it->l) + cnt(it->r) + 1; 24 | } 25 | void upd_sum(pitem it) { 26 | if(it) { 27 | it->fsum = it->key; 28 | if(it->l) it->fsum += it->l->fsum; 29 | if(it->r) it->fsum += it->r->fsum; 30 | } 31 | } 32 | void update(pitem t, T add, int rev) { 33 | if(!t) return; 34 | t->add = t->add + add; 35 | t->rev = t->rev ^ rev; 36 | t->key = t->key + add; 37 | t->fsum = t->fsum + cnt(t) * add; 38 | } 39 | void push(pitem t) { 40 | if(!t || (t->add == 0*T() && t->rev == 0)) return; 41 | update(t->l, t->add, t->rev); 42 | update(t->r, t->add, t->rev); 43 | if(t->rev) swap(t->l,t->r); 44 | t->add = 0*T(); t->rev = 0; 45 | } 46 | void merge(pitem & t, pitem l, pitem r) { 47 | push(l); push(r); 48 | if(!l || !r) t = l ? l : r; 49 | else if(l->prior > r->prior) merge(l->r, l->r, r), t = l; 50 | else merge(r->l, l, r->l), t = r; 51 | upd_cnt(t); upd_sum(t); 52 | } 53 | void split(pitem t, pitem & l, pitem & r, int index) { // split index = how many elements 54 | if(!t) return void(l = r = 0); 55 | push(t); 56 | if(index <= cnt(t->l)) split(t->l, l, t->l, index), r = t; 57 | else split(t->r, t->r, r, index - 1 - cnt(t->l)), l = t; 58 | upd_cnt(t); upd_sum(t); 59 | } 60 | void insert(pitem & t, pitem it, int index) { // insert at position 61 | push(t); 62 | if(!t) t = it; 63 | else if(it->prior > t->prior) split(t, it->l, it->r, index), t = it; 64 | else if(index <= cnt(t->l)) insert(t->l, it, index); 65 | else insert(t->r, it, index-cnt(t->l)-1); 66 | upd_cnt(t); upd_sum(t); 67 | } 68 | void erase(pitem & t, int index) { 69 | push(t); 70 | if(cnt(t->l) == index) merge(t, t->l, t->r); 71 | else if(index < cnt(t->l)) erase(t->l, index); 72 | else erase(t->r, index - cnt(t->l) - 1); 73 | upd_cnt(t); upd_sum(t); 74 | } 75 | T get(pitem t, int index) { 76 | push(t); 77 | if(index < cnt(t->l)) return get(t->l, index); 78 | else if(index > cnt(t->l)) return get(t->r, index - cnt(t->l) - 1); 79 | return t->key; 80 | } 81 | T query_sum (pitem &t, int l, int r) { 82 | pitem l1, r1; 83 | split (t, l1, r1, r + 1); 84 | pitem l2, r2; 85 | split (l1, l2, r2, l); 86 | T ret = r2->fsum; 87 | pitem t2; 88 | merge (t2, l2, r2); 89 | merge (t, t2, r1); 90 | return ret; 91 | } 92 | public: 93 | int size() { return cnt(root); } 94 | void insert(int pos, T x) { 95 | if(pos > size()) return; 96 | pitem it = new item(x, dis64(rng64)); 97 | insert(root, it, pos); 98 | } 99 | void erase(int pos) { 100 | if(pos >= size()) return; 101 | erase(root, pos); 102 | } 103 | T sum(int left, int right) { 104 | return query_sum(root, left, right); 105 | } 106 | T operator[](int index) { return get(root, index); } 107 | }; 108 | -------------------------------------------------------------------------------- /Data structures/Treap2.0.cpp: -------------------------------------------------------------------------------- 1 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 2 | uniform_int_distribution rnd(0, INT_MAX); 3 | 4 | typedef long long T; 5 | struct node { 6 | node *left, *right; 7 | int prior, sz; 8 | T value, lazy_sum, sum; 9 | node() { 10 | left = right = NULL; 11 | prior = rnd(rng); 12 | sz = 1; 13 | value = lazy_sum = sum = 0; 14 | } 15 | }; 16 | 17 | int cnt(node* t) { return !t ? 0 : t->sz; } 18 | int sum(node* t) { return !t ? 0 : t->sum; } 19 | 20 | void propagate(node* t) { 21 | if(t->lazy_sum) { 22 | if(t->left) t->left->lazy_sum += t->lazy_sum; 23 | if(t->right) t->right->lazy_sum += t->lazy_sum; 24 | t->sum += cnt(t) * t->lazy_sum; 25 | t->value += t->lazy_sum; 26 | t->lazy_sum = 0; 27 | } 28 | } 29 | 30 | void update(node *t) { 31 | t->sz = cnt(t->left) + cnt(t->right) + 1; 32 | t->value = sum(t->left) + sum(t->right) + t->value; 33 | } 34 | 35 | pair split(node* t, int left_count) { 36 | if(!t) return {NULL, NULL}; 37 | propagate(t); 38 | if(cnt(t->left) >= left_count) { 39 | auto got = split(t->left, left_count); 40 | t->left = got.second; 41 | update(t); 42 | return {got.first, t}; 43 | } else { 44 | left_count = left_count-cnt(t->left)-1; 45 | auto got = split(t->right, left_count); 46 | t->right = got.first; 47 | update(t); 48 | return {t, got.second}; 49 | } 50 | } 51 | 52 | node* merge(node *s, node *t) { 53 | if(!s) return t; 54 | if(!t) return s; 55 | propagate(s); 56 | propagate(t); 57 | if(s->prior <= t->prior) { 58 | s->right = merge(s->right, t); 59 | update(s); 60 | return s; 61 | } else { 62 | t->left = merge(s, t->left); 63 | update(t); 64 | return t; 65 | } 66 | } -------------------------------------------------------------------------------- /Dp optimization/Convex hull trick dynamic.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log(|N|)) 2 | /// Tested: Not yet 3 | typedef ll T; 4 | const T is_query = -(1LL<<62); // special value for query 5 | struct line { 6 | T m, b; 7 | mutable multiset::iterator it, end; 8 | const line* succ(multiset::iterator it) const { 9 | return (++it == end ? nullptr : &*it); 10 | } 11 | bool operator < (const line& rhs) const { 12 | if(rhs.b != is_query) return m < rhs.m; 13 | const line *s = succ(it); 14 | if(!s) return 0; 15 | return b-s->b < (s->m-m)*rhs.m; 16 | } 17 | }; 18 | struct hull_dynamic : public multiset { // for maximum 19 | bool bad(iterator y) { 20 | iterator z = next(y); 21 | if(y == begin()){ 22 | if(z == end()) return false; 23 | return y->m == z->m && y->b <= z->b; 24 | } 25 | iterator x = prev(y); 26 | if(z == end()) return y->m == x->m && y->b <= x->b; 27 | return (x->b - y->b)*(z->m - y->m) >= 28 | (y->b - z->b)*(y->m - x->m); 29 | } 30 | iterator next(iterator y){ return ++y; } 31 | iterator prev(iterator y){ return --y; } 32 | void add(T m, T b){ 33 | iterator y = insert((line){m, b}); 34 | y->it = y; y->end = end(); 35 | if(bad(y)){ erase(y); return; } 36 | while(next(y) != end() && bad(next(y))) erase(next(y)); 37 | while(y != begin() && bad(prev(y))) erase(prev(y)); 38 | } 39 | T eval(T x){ 40 | line l = *lower_bound((line){x, is_query}); 41 | return l.m*x+l.b; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /Dp optimization/Convex hull trick.cpp: -------------------------------------------------------------------------------- 1 | struct line { 2 | ll m, b; 3 | ll eval (ll x) { return m*x + b; } 4 | }; 5 | struct cht { 6 | vector lines; 7 | vector inter; 8 | int n; 9 | lf get_inter(line &a, line &b) { return lf(b.b - a.b) / (a.m - b.m); } 10 | inline bool ok(line &a, line &b, line &c) { 11 | return lf(a.b-c.b) / (c.m-a.m) > lf(a.b-b.b) / (b.m-a.m); 12 | } 13 | void add(line l) { 14 | n = lines.size(); 15 | if(n && lines.back().m == l.m && lines.back().b >= l.b) return; 16 | if(n == 1 && lines.back().m == l.m && lines.back().b < l.b) lines.pop_back(), n--; 17 | while(n >= 2 && !ok(lines[n-2], lines[n-1], l)) { 18 | n--; 19 | lines.pop_back(); inter.pop_back(); 20 | } 21 | lines.push_back(l); n++; 22 | if(n >= 2) inter.push_back(get_inter(lines[n-1], lines[n-2])); 23 | } 24 | ll get_max(lf x) { 25 | if(lines.size() == 0) return LLONG_MIN; 26 | if(lines.size() == 1) return lines[0].eval(x); 27 | int pos = lower_bound(inter.begin(), inter.end(), x) - inter.begin(); 28 | return lines[pos].eval(x); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /Dp optimization/Divide and conquer.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*|K|*log|N|)) 2 | /// ******* Theory ******* 3 | /// dp[k][i]=min(dp[k−1][j]+C[i][j]), j < i 4 | /// opt[k][i] ≤ opt[k][i+1]. 5 | /// A sufficient (but not necessary) condition for above is 6 | /// C[a][c] + C[b][d] ≤ C[a][d] + C[b][c] where a < b < c < d. 7 | void go(int k, int l, int r, int opl, int opr) { 8 | if(l > r) return; 9 | int mid = (l + r) / 2, op = -1; 10 | ll &best = dp[mid][k]; 11 | best = INF; 12 | for(int i = min(opr, mid); i >= opl; i--) { 13 | ll cur = dp[i][k-1] + cost(i+1, mid); 14 | if(best > cur) { 15 | best = cur; 16 | op = i; 17 | } 18 | } 19 | go(k, l, mid-1, opl, op); 20 | go(k, mid+1, r, op, opr); 21 | } 22 | -------------------------------------------------------------------------------- /Dp optimization/Knuth.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|^2)) 2 | /// Tested: https://tinyurl.com/y6ofp8wb 3 | /// ******* Theory ******* 4 | /// dp[i][j]= min(dp[i][k]+dp[k][j])+C[i][j], i n > 0$:\\ 3 | $a = m^2 - n^2$, $b = 2mn$, $c = m^2 + n^2$ 4 | \item The triple generated by Euclid's formula is primitive if and only if $m$ and $n$ are coprime and not both odd. 5 | \item To generate all Pythagorean triples uniquely:\\ 6 | $a = k (m^2 - n^2)$, $b = k(2mn)$, $c = k(m^2 + n^2)$ 7 | \item If $m$ and $n$ are two odd integer such that $m > n$, then:\\ 8 | $a = mn$, $b = \frac{m^2 - n^2}{2}$, $c = \frac{m^2 + n^2}{2}$ 9 | \item If $n=1$ or $2$ there are no solutions. Otherwise\\ 10 | $n$ is even: ($(\frac{n^2}{4} - 1)^2 + n^2 = (\frac{n^2}{4} + 1)^2$)\\ 11 | $n$ is odd: ($(\frac{n^2 - 1}{2})^2 + n^2 = (\frac{n^2 + 1}{2})^2$) 12 | \end{itemize} -------------------------------------------------------------------------------- /Formulas/Simplex Rules.tex: -------------------------------------------------------------------------------- 1 | The simplex algorithm operated on linear programs in standard form:\\ 2 | \textbf{Maximixe} : $c^{T} \cdot x$\\ 3 | \textbf{Subject to} : $Ax \leq b, x_i \geq 0$ 4 | \begin{itemize} 5 | \item $x = (x_1,...,x_n)$ the variables of the problem 6 | \item $c = (c_1,...,c_n)$ are the coefficients of the objective function 7 | \item $A$ is a $p \times n$ matrix and $b = (b_1,..., b_p)$ constants with $b_j \geq 0$ 8 | \end{itemize} -------------------------------------------------------------------------------- /Formulas/Sum of divisors of a number.tex: -------------------------------------------------------------------------------- 1 | \begin{itemize} 2 | \item $\sigma(n) = \prod_{i=1}^{k}(1 + p_{i} + ... + p_{i}^{\alpha_i}) = \prod_{i=1}^{k}\frac{p_{i}^{\alpha_i + 1} - 1}{p_i - 1}$ 3 | \end{itemize} -------------------------------------------------------------------------------- /Formulas/Summations.tex: -------------------------------------------------------------------------------- 1 | \begin{itemize} 2 | \item $\sum_{i=1}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}$ 3 | \item $\sum_{i=1}^{n} i^3 = (\frac{n(n+1)}{2})^2$ 4 | \item $\sum_{i=1}^{n} i^4 = \frac{n(n+1)(2n+1)(3n^2+3n-1)}{30}$ 5 | \item $\sum_{i=1}^{n} i^5 = \frac{(n(n+1))^2(2n^2+2n-1)}{12}$ 6 | \item $\sum_{i=0}^{n} x^i = \frac{x^{n+1}-1}{x-1}$ para $x \neq 1$ 7 | \end{itemize} -------------------------------------------------------------------------------- /Formulas/Theorems.tex: -------------------------------------------------------------------------------- 1 | \begin{itemize} 2 | \item There is always a prime between numbers $n^2$ and $(n+1)^2$, where $n$ is any positive integer 3 | \item There is an infinite number of pairs of the from $\{p, p + 2\}$ where both $p$ and $p + 2$ are primes. 4 | \item Every even integer greater than 2 can be expressed as the sum of two primes. 5 | \item Every integer greater than 2 can be written as the sum of three primes. 6 | \end{itemize} -------------------------------------------------------------------------------- /Geometry/3D.cpp: -------------------------------------------------------------------------------- 1 | typedef double T; 2 | struct p3 { 3 | T x, y, z; 4 | // Basic vector operations 5 | p3 operator + (p3 p) { return {x+p.x, y+p.y, z+p.z }; } 6 | p3 operator - (p3 p) { return {x - p.x, y - p.y, z - p.z}; } 7 | p3 operator * (T d) { return {x*d, y*d, z*d}; } 8 | p3 operator / (T d) { return {x / d, y / d, z / d}; } // only for floating point 9 | // Some comparators 10 | bool operator == (p3 p) { return tie(x, y, z) == tie(p.x, p.y, p.z); } 11 | bool operator != (p3 p) { return !operator == (p); } 12 | }; 13 | p3 zero {0, 0, 0 }; 14 | T operator | (p3 v, p3 w) { /// dot 15 | return v.x*w.x + v.y*w.y + v.z*w.z; 16 | } 17 | p3 operator * (p3 v, p3 w) { /// cross 18 | return { v.y*w.z - v.z*w.y, v.z*w.x - v.x*w.z, v.x*w.y - v.y*w.x }; 19 | } 20 | T sq(p3 v) { return v | v; } 21 | double abs(p3 v) { return sqrt(sq(v)); } 22 | p3 unit(p3 v) { return v / abs(v); } 23 | double angle(p3 v, p3 w) { 24 | double cos_theta = (v | w) / abs(v) / abs(w); 25 | return acos(max(-1.0, min(1.0, cos_theta))); 26 | } 27 | T orient(p3 p, p3 q, p3 r, p3 s) { /// orient s, pqr form a triangle 28 | return (q - p) * (r - p) | (s - p); 29 | } 30 | T orient_by_normal(p3 p, p3 q, p3 r, p3 n) { /// same as 2D but in n-normal direction 31 | return (q - p) * (r - p) | n; 32 | } 33 | struct plane { 34 | p3 n; T d; 35 | /// From normal n and offset d 36 | plane(p3 n, T d): n(n), d(d) {} 37 | /// From normal n and point P 38 | plane(p3 n, p3 p): n(n), d(n | p) {} 39 | /// From three non-collinear points P,Q,R 40 | plane(p3 p, p3 q, p3 r): plane((q - p) * (r - p), p) {} 41 | /// - these work with T = int 42 | T side(p3 p) { return (n | p) - d; } 43 | double dist(p3 p) { return abs(side(p)) / abs(n); } 44 | plane translate(p3 t) {return {n, d + (n | t)}; } 45 | /// - these require T = double 46 | plane shift_up(double dist) { return {n, d + dist * abs(n)}; } 47 | p3 proj(p3 p) { return p - n * side(p) / sq(n); } 48 | p3 refl(p3 p) { return p - n * 2 * side(p) / sq(n); } 49 | }; 50 | 51 | struct line3d { 52 | p3 d, o; 53 | /// From two points P, Q 54 | line3d(p3 p, p3 q): d(q - p), o(p) {} 55 | /// From two planes p1, p2 (requires T = double) 56 | line3d(plane p1, plane p2) { 57 | d = p1.n * p2.n; 58 | o = (p2.n * p1.d - p1.n * p2.d) * d / sq(d); 59 | } 60 | /// - these work with T = int 61 | double sq_dist(p3 p) { return sq(d * (p - o)) / sq(d); } 62 | double dist(p3 p) { return sqrt(sq_dist(p)); } 63 | bool cmp_proj(p3 p, p3 q) { return (d | p) < (d | q); } 64 | /// - these require T = double 65 | p3 proj(p3 p) { return o + d * (d | (p - o)) / sq(d); } 66 | p3 refl(p3 p) { return proj(p) * 2 - p; } 67 | p3 inter(plane p) { return o - d * p.side(o) / (p.n | d); } 68 | }; 69 | 70 | double dist(line3d l1, line3d l2) { 71 | p3 n = l1.d * l2.d; 72 | if(n == zero) // parallel 73 | return l1.dist(l2.o); 74 | return abs((l2.o - l1.o) | n) / abs(n); 75 | } 76 | p3 closest_on_line1(line3d l1, line3d l2) { /// closest point on l1 to l2 77 | p3 n2 = l2.d * (l1.d * l2.d); 78 | return l1.o + l1.d * ((l2.o - l1.o) | n2) / (l1.d | n2); 79 | } 80 | double small_angle(p3 v, p3 w) { return acos(min(abs(v | w) / abs(v) / abs(w), 1.0)); } 81 | double angle(plane p1, plane p2) { return small_angle(p1.n, p2.n); } 82 | bool is_parallel(plane p1, plane p2) { return p1.n * p2.n == zero; } 83 | bool is_perpendicular(plane p1, plane p2) { return (p1.n | p2.n) == 0; } 84 | double angle(line3d l1, line3d l2) { return small_angle(l1.d, l2.d); } 85 | bool is_parallel(line3d l1, line3d l2) { return l1.d * l2.d == zero; } 86 | bool is_perpendicular(line3d l1, line3d l2) { return (l1.d | l2.d) == 0; } 87 | double angle(plane p, line3d l) { return _pI / 2 - small_angle(p.n, l.d); } 88 | bool is_parallel(plane p, line3d l) { return (p.n | l.d) == 0; } 89 | bool is_perpendicular(plane p, line3d l) { return p.n * l.d == zero; } 90 | line3d perp_through(plane p, p3 o) { return line(o, o + p.n); } 91 | plane perp_through(line3d l, p3 o) { return plane(l.d, o); } 92 | -------------------------------------------------------------------------------- /Geometry/General.cpp: -------------------------------------------------------------------------------- 1 | const lf eps = 1e-9; 2 | typedef double T; 3 | struct pt { 4 | T x, y; 5 | pt operator + (pt p) { return {x+p.x, y+p.y}; } 6 | pt operator - (pt p) { return {x-p.x, y-p.y}; } 7 | pt operator * (pt p) { return {x*p.x-y*p.y, x*p.y+y*p.x}; } 8 | pt operator * (T d) { return {x*d, y*d}; } 9 | pt operator / (lf d) { return {x/d, y/d}; } /// only for floating point 10 | bool operator == (pt b) { return x == b.x && y == b.y; } 11 | bool operator != (pt b) { return !(*this == b); } 12 | bool operator < (const pt &o) const { return y < o.y || (y == o.y && x < o.x); } 13 | bool operator > (const pt &o) const { return y > o.y || (y == o.y && x > o.x); } 14 | }; 15 | int cmp (lf a, lf b) { return (a + eps < b ? -1 :(b + eps < a ? 1 : 0)); } 16 | /** Already in complex **/ 17 | T norm(pt a) { return a.x*a.x + a.y*a.y; } 18 | lf abs(pt a) { return sqrt(norm(a)); } 19 | lf arg(pt a) { return atan2(a.y, a.x); } 20 | ostream& operator << (ostream& os, pt &p) { 21 | return os << "("<< p.x << "," << p.y << ")"; 22 | } 23 | /***/ 24 | istream &operator >> (istream &in, pt &p) { 25 | T x, y; in >> x >> y; 26 | p = {x, y}; 27 | return in; 28 | } 29 | T dot(pt a, pt b) { return a.x*b.x + a.y*b.y; } 30 | T cross(pt a, pt b) { return a.x*b.y - a.y*b.x; } 31 | T orient(pt a, pt b, pt c) { return cross(b-a,c-a); } 32 | //pt rot(pt p, lf a) { return {p.x*cos(a) - p.y*sin(a), p.x*sin(a) + p.y*cos(a)}; } 33 | //pt rot(pt p, double a) { return p * polar(1.0, a); } /// for complex 34 | //pt rotate_to_b(pt a, pt b, lf ang) { return rot(a-b, ang)+b; } 35 | pt rot90ccw(pt p) { return {-p.y, p.x}; } 36 | pt rot90cw(pt p) { return {p.y, -p.x}; } 37 | pt translate(pt p, pt v) { return p+v; } 38 | pt scale(pt p, double f, pt c) { return c + (p-c)*f; } 39 | bool are_perp(pt v, pt w) { return dot(v,w) == 0; } 40 | int sign(T x) { return (T(0) < x) - (x < T(0)); } 41 | pt unit(pt a) { return a/abs(a); } 42 | 43 | bool in_angle(pt a, pt b, pt c, pt x) { 44 | assert(orient(a,b,c) != 0); 45 | if (orient(a,b,c) < 0) swap(b,c); 46 | return orient(a,b,x) >= 0 && orient(a,c,x) <= 0; 47 | } 48 | 49 | //lf angle(pt a, pt b) { return acos(max(-1.0, min(1.0, dot(a,b)/abs(a)/abs(b)))); } 50 | //lf angle(pt a, pt b) { return atan2(cross(a, b), dot(a, b)); } 51 | /// returns vector to transform points 52 | pt get_linear_transformation(pt p, pt q, pt r, pt fp, pt fq) { 53 | pt pq = q-p, num{cross(pq, fq-fp), dot(pq, fq-fp)}; 54 | return fp + pt{cross(r-p, num), dot(r-p, num)} / norm(pq); 55 | } 56 | 57 | bool half(pt p) { /// true if is in (0, 180] 58 | assert(p.x != 0 || p.y != 0); /// the argument of (0,0) is undefined 59 | return p.y > 0 || (p.y == 0 && p.x < 0); 60 | } 61 | bool half_from(pt p, pt v = {1, 0}) { 62 | return cross(v,p) < 0 || (cross(v,p) == 0 && dot(v,p) < 0); 63 | } 64 | bool polar_cmp(const pt &a, const pt &b) { 65 | return make_tuple(half(a), 0) < make_tuple(half(b), cross(a,b)); 66 | } 67 | 68 | struct line { 69 | pt v; T c; 70 | line(pt v, T c) : v(v), c(c) {} 71 | line(T a, T b, T c) : v({b,-a}), c(c) {} 72 | line(pt p, pt q) : v(q-p), c(cross(v,p)) {} 73 | T side(pt p) { return cross(v,p)-c; } 74 | lf dist(pt p) { return abs(side(p)) / abs(v); } 75 | lf sq_dist(pt p) { return side(p)*side(p) / (lf)norm(v); } 76 | line perp_through(pt p) { return {p, p + rot90ccw(v)}; } 77 | bool cmp_proj(pt p, pt q) { return dot(v,p) < dot(v,q); } 78 | line translate(pt t) { return {v, c + cross(v,t)}; } 79 | line shift_left(double d) { return {v, c + d*abs(v)}; } 80 | pt proj(pt p) { return p - rot90ccw(v)*side(p)/norm(v); } 81 | pt refl(pt p) { return p - rot90ccw(v)*2*side(p)/norm(v); } 82 | }; 83 | 84 | bool inter_ll(line l1, line l2, pt &out) { 85 | T d = cross(l1.v, l2.v); 86 | if (d == 0) return false; 87 | out = (l2.v*l1.c - l1.v*l2.c) / d; 88 | return true; 89 | } 90 | line bisector(line l1, line l2, bool interior) { 91 | assert(cross(l1.v, l2.v) != 0); /// l1 and l2 cannot be parallel! 92 | lf sign = interior ? 1 : -1; 93 | return {l2.v/abs(l2.v) + l1.v/abs(l1.v) * sign, 94 | l2.c/abs(l2.v) + l1.c/abs(l1.v) * sign}; 95 | } 96 | 97 | bool in_disk(pt a, pt b, pt p) { 98 | return dot(a-p, b-p) <= 0; 99 | } 100 | bool on_segment(pt a, pt b, pt p) { 101 | return orient(a,b,p) == 0 && in_disk(a,b,p); 102 | } 103 | bool proper_inter(pt a, pt b, pt c, pt d, pt &out) { 104 | T oa = orient(c,d,a), 105 | ob = orient(c,d,b), 106 | oc = orient(a,b,c), 107 | od = orient(a,b,d); 108 | /// Proper intersection exists iff opposite signs 109 | if (oa*ob < 0 && oc*od < 0) { 110 | out = (a*ob - b*oa) / (ob-oa); 111 | return true; 112 | } 113 | return false; 114 | } 115 | set inter_ss(pt a, pt b, pt c, pt d) { 116 | pt out; 117 | if (proper_inter(a,b,c,d,out)) return {out}; 118 | set s; 119 | if (on_segment(c,d,a)) s.insert(a); 120 | if (on_segment(c,d,b)) s.insert(b); 121 | if (on_segment(a,b,c)) s.insert(c); 122 | if (on_segment(a,b,d)) s.insert(d); 123 | return s; 124 | } 125 | lf pt_to_seg(pt a, pt b, pt p) { 126 | if(a != b) { 127 | line l(a,b); 128 | if (l.cmp_proj(a,p) && l.cmp_proj(p,b)) /// if closest to projection 129 | return l.dist(p); /// output distance to line 130 | } 131 | return min(abs(p-a), abs(p-b)); /// otherwise distance to A or B 132 | } 133 | lf seg_to_seg(pt a, pt b, pt c, pt d) { 134 | pt dummy; 135 | if (proper_inter(a,b,c,d,dummy)) return 0; 136 | return min({pt_to_seg(a,b,c), pt_to_seg(a,b,d), 137 | pt_to_seg(c,d,a), pt_to_seg(c,d,b)}); 138 | } 139 | 140 | enum {IN, OUT, ON}; 141 | struct polygon { 142 | vector p; 143 | polygon(int n) : p(n) {} 144 | int top = -1, bottom = -1; 145 | void delete_repetead() { 146 | vector aux; 147 | sort(p.begin(), p.end()); 148 | for(pt &i : p) 149 | if(aux.empty() || aux.back() != i) 150 | aux.push_back(i); 151 | p.swap(aux); 152 | } 153 | bool is_convex() { 154 | bool pos = 0, neg = 0; 155 | for (int i = 0, n = p.size(); i < n; i++) { 156 | int o = orient(p[i], p[(i+1)%n], p[(i+2)%n]); 157 | if (o > 0) pos = 1; 158 | if (o < 0) neg = 1; 159 | } 160 | return !(pos && neg); 161 | } 162 | lf area(bool s = false) { 163 | lf ans = 0; 164 | for (int i = 0, n = p.size(); i < n; i++) 165 | ans += cross(p[i], p[(i+1)%n]); 166 | ans /= 2; 167 | return s ? ans : abs(ans); 168 | } 169 | lf perimeter() { 170 | lf per = 0; 171 | for(int i = 0, n = p.size(); i < n; i++) 172 | per += abs(p[i] - p[(i+1)%n]); 173 | return per; 174 | } 175 | bool above(pt a, pt p) { return p.y >= a.y; } 176 | bool crosses_ray(pt a, pt p, pt q) { 177 | return (above(a,q)-above(a,p))*orient(a,p,q) > 0; 178 | } 179 | int in_polygon(pt a) { 180 | int crosses = 0; 181 | for(int i = 0, n = p.size(); i < n; i++) { 182 | if(on_segment(p[i], p[(i+1)%n], a)) return ON; 183 | crosses += crosses_ray(a, p[i], p[(i+1)%n]); 184 | } 185 | return (crosses&1 ? IN : OUT); 186 | } 187 | void normalize() { /// polygon is CCW 188 | bottom = min_element(p.begin(), p.end()) - p.begin(); 189 | vector tmp(p.begin()+bottom, p.end()); 190 | tmp.insert(tmp.end(), p.begin(), p.begin()+bottom); 191 | p.swap(tmp); 192 | bottom = 0; 193 | top = max_element(p.begin(), p.end()) - p.begin(); 194 | } 195 | int in_convex(pt a) { 196 | assert(bottom == 0 && top != -1); 197 | if(a < p[0] || a > p[top]) return OUT; 198 | T orientation = orient(p[0], p[top], a); 199 | if(orientation == 0) { 200 | if(a == p[0] || a == p[top]) return ON; 201 | return top == 1 || top + 1 == p.size() ? ON : IN; 202 | } else if (orientation < 0) { 203 | auto it = lower_bound(p.begin()+1, p.begin()+top, a); 204 | T d = orient(*prev(it), a, *it); 205 | return d < 0 ? IN : (d > 0 ? OUT: ON); 206 | } 207 | else { 208 | auto it = upper_bound(p.rbegin(), p.rend()-top-1, a); 209 | T d = orient(*it, a, it == p.rbegin() ? p[0] : *prev(it)); 210 | return d < 0 ? IN : (d > 0 ? OUT: ON); 211 | } 212 | } 213 | polygon cut(pt a, pt b) { 214 | line l(a, b); 215 | polygon new_polygon(0); 216 | for(int i = 0, n = p.size(); i < n; ++i) { 217 | pt c = p[i], d = p[(i+1)%n]; 218 | lf abc = cross(b-a, c-a), abd = cross(b-a, d-a); 219 | if(abc >= 0) new_polygon.p.push_back(c); 220 | if(abc*abd < 0) { 221 | pt out; inter_ll(l, line(c, d), out); 222 | new_polygon.p.push_back(out); 223 | } 224 | } 225 | return new_polygon; 226 | } 227 | void convex_hull() { 228 | sort(p.begin(), p.end()); 229 | vector ch; 230 | ch.reserve(p.size()+1); 231 | for(int it = 0; it < 2; it++) { 232 | int start = ch.size(); 233 | for(auto &a : p) { 234 | /// if colineal are needed, use < and remove repeated points 235 | while(ch.size() >= start+2 && orient(ch[ch.size()-2], ch.back(), a) <= 0) 236 | ch.pop_back(); 237 | ch.push_back(a); 238 | } 239 | ch.pop_back(); 240 | reverse(p.begin(), p.end()); 241 | } 242 | if(ch.size() == 2 && ch[0] == ch[1]) ch.pop_back(); 243 | /// be careful with CH of size < 3 244 | p.swap(ch); 245 | } 246 | vector antipodal() { 247 | vector ans; 248 | int n = p.size(); 249 | if(n == 2) ans.push_back({0, 1}); 250 | if(n < 3) return ans; 251 | auto nxt = [&](int x) { return (x+1 == n ? 0 : x+1); }; 252 | auto area2 = [&](pt a, pt b, pt c) { return cross(b-a, c-a); }; 253 | int b0 = 0; 254 | while(abs(area2(p[n - 1], p[0], p[nxt(b0)])) > 255 | abs(area2(p[n - 1], p[0], p[b0]))) 256 | ++b0; 257 | for(int b = b0, a = 0; b != 0 && a <= b0; ++a) { 258 | ans.push_back({a, b}); 259 | while (abs(area2(p[a], p[nxt(a)], p[nxt(b)])) > 260 | abs(area2(p[a], p[nxt(a)], p[b]))) { 261 | b = nxt(b); 262 | if(a != b0 || b != 0) ans.push_back({ a, b }); 263 | else return ans; 264 | } 265 | if(abs(area2(p[a], p[nxt(a)], p[nxt(b)])) == 266 | abs(area2(p[a], p[nxt(a)], p[b]))) { 267 | if(a != b0 || b != n-1) ans.push_back({ a, nxt(b) }); 268 | else ans.push_back({ nxt(a), b }); 269 | } 270 | } 271 | return ans; 272 | } 273 | pt centroid() { 274 | pt c{0, 0}; 275 | lf scale = 6. * area(true); 276 | for(int i = 0, n = p.size(); i < n; ++i) { 277 | int j = (i+1 == n ? 0 : i+1); 278 | c = c + (p[i] + p[j]) * cross(p[i], p[j]); 279 | } 280 | return c / scale; 281 | } 282 | ll pick() { 283 | ll boundary = 0; 284 | for(int i = 0, n = p.size(); i < n; i++) { 285 | int j = (i+1 == n ? 0 : i+1); 286 | boundary += __gcd((ll)abs(p[i].x - p[j].x), (ll)abs(p[i].y - p[j].y)); 287 | } 288 | return area() + 1 - boundary/2; 289 | } 290 | pt& operator[] (int i){ return p[i]; } 291 | }; 292 | 293 | struct circle { 294 | pt c; T r; 295 | }; 296 | 297 | circle center(pt a, pt b, pt c) { 298 | b = b-a, c = c-a; 299 | assert(cross(b,c) != 0); /// no circumcircle if A,B,C aligned 300 | pt cen = a + rot90ccw(b*norm(c) - c*norm(b))/cross(b,c)/2; 301 | return {cen, abs(a-cen)}; 302 | } 303 | int inter_cl(circle c, line l, pair &out) { 304 | lf h2 = c.r*c.r - l.sq_dist(c.c); 305 | if(h2 >= 0) { 306 | pt p = l.proj(c.c); 307 | pt h = l.v*sqrt(h2)/abs(l.v); 308 | out = {p-h, p+h}; 309 | } 310 | return 1 + sign(h2); 311 | } 312 | int inter_cc(circle c1, circle c2, pair &out) { 313 | pt d=c2.c-c1.c; double d2=norm(d); 314 | if(d2 == 0) { assert(c1.r != c2.r); return 0; } // concentric circles 315 | double pd = (d2 + c1.r*c1.r - c2.r*c2.r)/2; // = |O_1P| * d 316 | double h2 = c1.r*c1.r - pd*pd/d2; // = h�2 317 | if(h2 >= 0) { 318 | pt p = c1.c + d*pd/d2, h = rot90ccw(d)*sqrt(h2/d2); 319 | out = {p-h, p+h}; 320 | } 321 | return 1 + sign(h2); 322 | } 323 | 324 | int tangents(circle c1, circle c2, bool inner, vector> &out) { 325 | if(inner) c2.r = -c2.r; 326 | pt d = c2.c-c1.c; 327 | double dr = c1.r-c2.r, d2 = norm(d), h2 = d2-dr*dr; 328 | if(d2 == 0 || h2 < 0) { assert(h2 != 0); return 0; } 329 | for(double s : {-1,1}) { 330 | pt v = (d*dr + rot90ccw(d)*sqrt(h2)*s)/d2; 331 | out.push_back({c1.c + v*c1.r, c2.c + v*c2.r}); 332 | } 333 | return 1 + (h2 > 0); 334 | } 335 | 336 | int tangent_through_pt(pt p, circle c, pair &out) { 337 | double d = abs(p - c.c); 338 | if(d < c.r) return 0; 339 | pt base = c.c-p; 340 | double w = sqrt(norm(base) - c.r*c.r); 341 | pt a = {w, c.r}, b = {w, -c.r}; 342 | pt s = p + base*a/norm(base)*w; 343 | pt t = p + base*b/norm(base)*w; 344 | out = {s, t}; 345 | return 1 + (abs(c.c-p) == c.r); 346 | } 347 | -------------------------------------------------------------------------------- /Geometry/nonTested.cpp: -------------------------------------------------------------------------------- 1 | 2 | lf part(pt a, pt b, T r) { 3 | lf l = abs(a-b); 4 | pt p = (b-a)/l; 5 | lf c = dot(a, p), d = 4.0 * (c*c - dot(a, a) + r*r); 6 | if (d < eps) return angle(a, b) * r * r * 0.5; 7 | d = sqrt(d) * 0.5; 8 | lf s = -c - d, t = -c + d; 9 | if (s < 0.0) s = 0.0; else if (s > l) s = l; 10 | if (t < 0.0) t = 0.0; else if (t > l) t = l; 11 | pt u = a + p*s, v = a + p*t; 12 | return (cross(u, v) + (angle(a, u) + angle(v, b)) * r * r) * 0.5; 13 | } 14 | lf inter_cp(circle c, polygon p) { 15 | lf ans = 0; 16 | int n = p.p.size(); 17 | for (int i = 0; i < n; i++) { 18 | ans += part(p[i]-c.c, p[(i+1)%4]-c.c, c.r); 19 | } 20 | return abs(ans); 21 | } 22 | struct circle{ 23 | point center; double r; 24 | bool contain(point &p) { return abs(center - p) < r + eps;} 25 | }; 26 | T cross(point a, point b) { return a.x*b.y - a.y*b.x; } 27 | point rot90ccw(point p) { return {-p.y, p.x}; } 28 | point get(point a, point b, point c) { 29 | b = b-a, c = c-a; 30 | //assert(cross(b,c) != 0); /// no circumcircle if A,B,C aligned 31 | point cen = a + rot90ccw(b*norm(c) - c*norm(b))/cross(b,c)/2; 32 | return cen; 33 | } 34 | 35 | circle min_circle(vector &cloud, int a, int b){ 36 | point center = (cloud[a] + cloud[b]) / double(2.); 37 | double rat = abs(center - cloud[a]); 38 | circle C = {center, rat}; 39 | for (int i = 0; i < b; ++i){ 40 | point x = cloud[i]; 41 | if (C.contain(x)) continue; 42 | center = get( cloud[a], cloud[b], cloud[i] ); 43 | rat = abs(center - cloud[a]); 44 | C = {center, rat}; 45 | } 46 | return C; 47 | } 48 | 49 | circle min_circle(vector &cloud, int a){ 50 | point center = (cloud[a] + cloud[0]) / double(2.); 51 | double rat = abs(center - cloud[a]); 52 | circle C = {center, rat}; 53 | for (int i = 0; i < a; ++i){ 54 | point x = cloud[i]; 55 | if (C.contain(x)) continue; 56 | C = min_circle(cloud, a, i); 57 | } 58 | return C; 59 | } 60 | circle min_circle(vector cloud){ 61 | // random_shuffle(cloud.begin(), cloud.end()); 62 | int n = (int)cloud.size(); 63 | for (int i = 1; i < n; ++i){ 64 | int u = rand() % i; 65 | swap(cloud[u], cloud[i]); 66 | } 67 | point center = (cloud[0] + cloud[1]) / double(2.); 68 | double rat = abs(center - cloud[0]); 69 | circle C = {center, rat}; 70 | for (int i = 2; i < n; ++i){ 71 | point x = cloud[i]; 72 | if (C.contain(x)) continue; 73 | C = min_circle(cloud, i); 74 | } 75 | return C; 76 | } -------------------------------------------------------------------------------- /Graphs/2-satisfiability.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/y8qhbzn4 3 | struct sat2 { 4 | int n; 5 | vector>> g; 6 | vector tag; 7 | vector seen, value; 8 | stack st; 9 | sat2(int n) : n(n), g(2, vector>(2*n)), tag(2*n), seen(2*n), value(2*n) { } 10 | int neg(int x) { return 2*n-x-1; } 11 | void add_or(int u, int v) { implication(neg(u), v); } 12 | void make_true(int u) { add_edge(neg(u), u); } 13 | void make_false(int u) { make_true(neg(u)); } 14 | void eq(int u, int v) { 15 | implication(u, v); 16 | implication(v, u); 17 | } 18 | void diff(int u, int v) { eq(u, neg(v)); } 19 | void implication(int u, int v) { 20 | add_edge(u, v); 21 | add_edge(neg(v), neg(u)); 22 | } 23 | void add_edge(int u, int v) { 24 | g[0][u].push_back(v); 25 | g[1][v].push_back(u); 26 | } 27 | void dfs(int id, int u, int t = 0) { 28 | seen[u] = true; 29 | for(auto& v : g[id][u]) 30 | if(!seen[v]) 31 | dfs(id, v, t); 32 | if(id == 0) st.push(u); 33 | else tag[u] = t; 34 | } 35 | void kosaraju() { 36 | for(int u = 0; u < n; u++) { 37 | if(!seen[u]) dfs(0, u); 38 | if(!seen[neg(u)]) dfs(0, neg(u)); 39 | } 40 | fill(seen.begin(), seen.end(), false); 41 | int t = 0; 42 | while(!st.empty()) { 43 | int u = st.top(); st.pop(); 44 | if(!seen[u]) dfs(1, u, t++); 45 | } 46 | } 47 | bool satisfiable() { 48 | kosaraju(); 49 | for(int i = 0; i < n; i++) { 50 | if(tag[i] == tag[neg(i)]) return false; 51 | value[i] = tag[i] > tag[neg(i)]; 52 | } 53 | return true; 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /Graphs/Erdos–Gallai theorem.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log|N|) 2 | /// Tested: https://tinyurl.com/yb5v9bau 3 | /// Theorem: it gives a necessary and sufficient condition for a finite sequence 4 | /// of natural numbers to be the degree sequence of a simple graph 5 | bool erdos(vector &d) { 6 | ll sum = 0; 7 | for(int i = 0; i < d.size(); ++i) sum += d[i]; 8 | if(sum & 1) return false; 9 | sort(d.rbegin(), d.rend()); 10 | ll l = 0, r = 0; 11 | for(int k = 1, i = d.size() - 1; k <= d.size(); ++k) { 12 | l += d[k-1]; 13 | if(k > i) r -= d[++i]; 14 | while (i >= k && d[i] < k+1) r += d[i--]; 15 | if(l > 1ll*k*(k-1) + 1ll*k*(i-k+1) + r) 16 | return false; 17 | } 18 | return true; 19 | } 20 | -------------------------------------------------------------------------------- /Graphs/Eulerian path.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/y85t8e83 3 | struct edge { 4 | int v; //list::iterator rev; 5 | edge(int v) : v(v) {} 6 | }; 7 | void add_edge(int a, int b) { 8 | g[a].push_front(edge(b)); // auto ia = g[a].begin(); 9 | g[b].push_front(edge(a)); // auto ib = g[b].begin(); 10 | //ia->rev=ib; ib->rev=ia; 11 | } 12 | /// for undirected uncomment and check for path existance 13 | bool eulerian(vector &tour) { /// directed graph 14 | int one_in = 0, one_out = 0, start = -1; 15 | bool ok = true; 16 | for (int i = 0; i < n; i++) { 17 | if(out[i] && start == -1) start = i; 18 | if(out[i] - in[i] == 1) one_out++, start = i; 19 | else if(in[i] - out[i] == 1) one_in++; 20 | else ok &= in[i] == out[i]; 21 | } 22 | ok &= one_in == one_out && one_in <= 1; 23 | if (ok) { 24 | function go = [&](int u) { 25 | while(g[u].size()) { 26 | int v = g[u].front().v; 27 | g[v].erase(g[u].front().rev); 28 | g[u].pop_front(); 29 | go(v, tour); 30 | } 31 | tour.push_back(u); 32 | }; 33 | go(start); 34 | reverse(tour.begin(), tour.end()); 35 | if(tour.size() == edges + 1) return true; 36 | } 37 | return false; 38 | } 39 | -------------------------------------------------------------------------------- /Graphs/Lowest common ancestor.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log|N|) 2 | /// Tested: https://tinyurl.com/y9g2ljv9, https://tinyurl.com/y87q3j93 3 | int lca(int a, int b) { 4 | if(depth[a] < depth[b]) swap(a, b); 5 | //int ans = INT_MAX; 6 | for(int i = LOG2-1; i >= 0; --i) 7 | if(depth[ dp[a][i] ] >= depth[b]) { 8 | //ans = min(ans, mn[a][i]); 9 | a = dp[a][i]; 10 | } 11 | //if (a == b) return ans; 12 | if(a == b) return a; 13 | for(int i = LOG2-1; i >= 0; --i) 14 | if(dp[a][i] != dp[b][i]) { 15 | //ans = min(ans, mn[a][i]); 16 | //ans = min(ans, mn[b][i]); 17 | a = dp[a][i], 18 | b = dp[b][i]; 19 | } 20 | //ans = min(ans, mn[a][0]); 21 | //ans = min(ans, mn[b][0]); 22 | //return ans; 23 | return dp[a][0]; 24 | } 25 | void dfs(int u, int d = 1, int p = -1) { 26 | depth[u] = d; 27 | for(auto v : g[u]) { 28 | //int v = x.first; 29 | //int w = x.second; 30 | if(v != p) { 31 | dfs(v, d + 1, u); 32 | dp[v][0] = u; 33 | //mn[v][0] = w; 34 | } 35 | } 36 | } 37 | void build(int n) { 38 | for(int i = 0; i <= n; i++) dp[i][0] = -1; 39 | for(int i = 0; i < n, i++) { 40 | if(dp[i][0] == -1) { 41 | dp[i][0] = i; 42 | //mn[i][0] = INT_MAX; 43 | dfs(i); 44 | } 45 | } 46 | 47 | for(int j = 0; j < LOG2-1; ++j) 48 | for(int i = 0; i <= n; ++i) { // nodes 49 | dp[i][j+1] = dp[ dp[i][j] ][j]; 50 | //mn[i][j+1] = min(mn[ dp[i][j] ][j], mn[i][j]); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Graphs/Number of spanning trees.cpp: -------------------------------------------------------------------------------- 1 | /// Tested: not yet 2 | ///A -> adjacency matrix 3 | ///It is necessary to compute the D-A matrix, where D is a diagonal matrix 4 | ///that contains the degree of each node. 5 | ///To compute the number of spanning trees it's necessary to compute any 6 | ///D-A cofactor 7 | ///C(i, j) = (-1)^(i+j) * Mij 8 | ///Where Mij is the matrix determinant after removing row i and column j 9 | double mat[MAX][MAX]; 10 | ///call determinant(n - 1) 11 | double determinant(int n) { 12 | double det = 1.0; 13 | for(int k = 0; k < n; k++) { 14 | for(int i = k+1; i < n; i++) { 15 | assert(mat[k][k] != 0); 16 | long double factor = mat[i][k]/mat[k][k]; 17 | for(int j = 0; j < n; j++) { 18 | mat[i][j] = mat[i][j] - factor*mat[k][j]; 19 | } 20 | } 21 | det *= mat[k][k]; 22 | } 23 | return round(det); 24 | } 25 | -------------------------------------------------------------------------------- /Graphs/Scc.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/y8ujj3ws 3 | int scc(int n) { 4 | vector dfn(n+1), low(n+1), in_stack(n+1); 5 | stack st; 6 | int tag = 0; 7 | function dfs = [&](int u, int &t) { 8 | dfn[u] = low[u] = ++t; 9 | st.push(u); 10 | in_stack[u] = true; 11 | for(auto &v : g[u]) { 12 | if(!dfn[v]) { 13 | dfs(v, t); 14 | low[u] = min(low[u], low[v]); 15 | } else if(in_stack[v]) 16 | low[u] = min(low[u], dfn[v]); 17 | } 18 | if (low[u] == dfn[u]) { 19 | int v; 20 | do { 21 | v = st.top(); st.pop(); 22 | // id[v] = tag; 23 | in_stack[v] = false; 24 | } while (v != u); 25 | tag++; 26 | } 27 | }; 28 | for(int u = 1, t; u <= n; ++u) { 29 | if(!dfn[u]) dfs(u, t = 0); 30 | } 31 | return tag; 32 | } 33 | -------------------------------------------------------------------------------- /Graphs/Tarjan tree.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/y9g2ljv9, https://tinyurl.com/y87q3j93 3 | struct tarjan_tree { 4 | int n; 5 | vector> g, comps; 6 | vector bridge; 7 | vector id, art; 8 | tarjan_tree(int n) : n(n), g(n+1), id(n+1), art(n+1) {} 9 | void add_edge(vector> &g, int u, int v) { /// nodes from [1, n] 10 | g[u].push_back(v); 11 | g[v].push_back(u); 12 | } 13 | void add_edge(int u, int v) { add_edge(g, u, v); } 14 | void tarjan(bool with_bridge) { 15 | vector dfn(n+1), low(n+1); 16 | stack st; 17 | comps.clear(); 18 | function dfs = [&](int u, int p, int &t) { 19 | dfn[u] = low[u] = ++t; 20 | st.push(u); 21 | int cntp = 0; 22 | for(int v : g[u]) { 23 | cntp += v == p; 24 | if(!dfn[v]) { 25 | dfs(v, u, t); 26 | low[u] = min(low[u], low[v]); 27 | if(with_bridge && low[v] > dfn[u]) { 28 | bridge.push_back({min(u,v), max(u,v)}); 29 | comps.push_back({}); 30 | for(int w = -1; w != v; ) 31 | comps.back().push_back(w = st.top()), st.pop(); 32 | } 33 | if(!with_bridge && low[v] >= dfn[u]) { 34 | art[u] = (dfn[u] > 1 || dfn[v] > 2); 35 | comps.push_back({u}); 36 | for(int w = -1; w != v; ) 37 | comps.back().push_back(w = st.top()), st.pop(); 38 | } 39 | } 40 | else if(v != p || cntp > 1) low[u] = min(low[u], dfn[v]); 41 | } 42 | if(p == -1 && ( with_bridge || g[u].size() == 0 )) { 43 | comps.push_back({}); 44 | for(int w = -1; w != u; ) 45 | comps.back().push_back(w = st.top()), st.pop(); 46 | } 47 | }; 48 | for(int u = 1, t; u <= n; ++u) 49 | if(!dfn[u]) dfs(u, -1, t = 0); 50 | } 51 | vector> build_block_cut_tree() { 52 | tarjan(false); 53 | int t = 0; 54 | for(int u = 1; u <= n; ++u) 55 | if(art[u]) id[u] = t++; 56 | vector> tree(t+comps.size()); 57 | for(int i = 0; i < comps.size(); ++i) 58 | for(int u : comps[i]) { 59 | if(!art[u]) id[u] = i+t; 60 | else add_edge(tree, i+t, id[u]); 61 | } 62 | return tree; 63 | } 64 | vector> build_bridge_tree() { 65 | tarjan(true); 66 | vector> tree(comps.size()); 67 | for(int i = 0; i < comps.size(); ++i) 68 | for(int u : comps[i]) id[u] = i; 69 | for(auto &b : bridge) 70 | add_edge(tree, id[b.first], id[b.second]); 71 | return tree; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /Graphs/Tree binarization.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: Not yet 3 | void add(int u, int v, int w) { ng[u].push_back({v, w}); } 4 | void binarize(int u, int p = -1) { 5 | int last = u, f = 0; 6 | for(auto x : g[u]) { 7 | int v = x.first, w = x.second, node = ng.size(); 8 | if(v == p) continue; 9 | if(f++) { 10 | ng.push_back({}); 11 | add(last, node, 0); 12 | add(node, v, w); 13 | last = node; 14 | } else add(u, v, w); 15 | binarize(v, u); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Graphs/Yen.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O( |K|*|N|^3 ) 2 | /// Tested: not yet 3 | int n; 4 | vector graph[ MAXN ]; 5 | int cost[ MAXN ][ MAXN ], dist[ MAXN ], connect[ MAXP ], path[ MAXN ]; 6 | ll vis = 0, mark = 0, edge[ MAXN ]; 7 | vector emp; 8 | struct Path { 9 | int w; 10 | vector p; 11 | Path( ) : w(0) { } 12 | Path( int w ) : w(w) { } 13 | Path( int w, vector p ) : w(w), p(p) { } 14 | bool operator < ( const Path& other )const { 15 | if( w == other.w ) { 16 | return lexicographical_compare( p.begin(), p.end(), other.p.begin(), other.p.end() ); 17 | } 18 | return w < other.w; 19 | } 20 | bool operator > ( const Path& other )const { 21 | if( w == other.w ){ 22 | return lexicographical_compare( other.p.begin(), other.p.end(), p.begin(), p.end() ); 23 | } 24 | return w > other.w; 25 | } 26 | }; 27 | 28 | void add_edge( int u, int v, int w ) { 29 | cost[u][v] = w; 30 | edge[u] |= ( 1LL<, greater > pq; 36 | fill( dist, dist+n+1, INF ); 37 | pq.push( {0,s} ); 38 | dist[s] = 0; 39 | while( !pq.empty() ) { 40 | int u = pq.top().second, c = pq.top().first; 41 | pq.pop(); 42 | if( u == t ) break; 43 | if( ((vis>>u)&1) && s != u ) 44 | continue; 45 | vis |= ( 1LL<>v)&1) || ( s == u && !((mark>>v)&1)) ) { 49 | continue; 50 | } 51 | if( cost[u][v] != INF && dist[v] >= c+cost[u][v] ) { 52 | if( dist[v] > c+cost[u][v] || ( dist[v] == c+cost[u][v] && u < path[v] ) ) { 53 | dist[v] = c+cost[u][v]; 54 | path[v] = u; 55 | pq.push( {dist[v], v} ); 56 | } 57 | } 58 | } 59 | } 60 | if( dist[t] == INF ) { 61 | return Path(); 62 | } 63 | Path ret( dist[t] ); 64 | for( int u = t; u != s; u = path[u] ) { 65 | ret.p.push_back( u ); 66 | } 67 | ret.p.push_back( s ); 68 | reverse( ret.p.begin(), ret.p.end() ); 69 | return ret; 70 | } 71 | 72 | vector yen( int s, int t, int k ) { 73 | priority_queue< Path, vector, greater > B; 74 | vector> A( MAXP ); 75 | vis = 0; 76 | mark = edge[s]; 77 | A[0] = dijkstra( s, t ).p; 78 | if( A[0].size() == 0 ) { 79 | return A[0]; 80 | } 81 | for( int it = 1; it < k; ++it ){ 82 | Path root_path; 83 | memset( connect, -1, sizeof(connect) ); 84 | vis = 0; 85 | bool F = true; 86 | for( int i = 0; i < A[it-1].size()-1; ++i ) { 87 | bool flag = false; 88 | if( F && it > 2 && A[it-1].size() > i+1 && 89 | A[it-2].size() > i+1 && A[it-1][i+1] == A[it-2][i+1] ) flag = true; 90 | else F = false; 91 | if( i >= A[it-1].size()-1 ) continue; 92 | int spur_node = A[it-1][i]; 93 | mark = edge[ spur_node ]; 94 | root_path.w += ( i ? cost[ A[it-1][i-1] ][ spur_node ] : 0 ); 95 | root_path.p.push_back( spur_node ); 96 | vis |= ( 1LL< i && A[j][i] == spur_node ) { 99 | connect[j] = i; 100 | if( A[j].size() > i+1 ) { 101 | mark &= ~( 1LL< 2 | 3 | using namespace std; 4 | 5 | const int mod = 998244353; 6 | 7 | inline int pw(int a, int b) { 8 | int ans = 1; 9 | while (b) { 10 | if (b & 1) ans = 1 LL * ans * a % mod; 11 | a = 1 LL * a * a % mod; 12 | b >>= 1; 13 | } 14 | return ans; 15 | } 16 | 17 | namespace linear_seq { 18 | int m; 19 | // a = first m terms 20 | // p = dependence, length is m 21 | vector < int > p, a; 22 | 23 | inline vector < int > BM(vector < int > x) { // finds shortest linear recurrence given first x terms in O(x^2) 24 | //ls = last s' recurrence 25 | vector < int > ls, cur; 26 | //ld = last t' found 27 | //lf delta of last found 28 | int lf, ld; 29 | for (int i = 0; i < (int) x.size(); ++i) { 30 | int t = 0; 31 | //evaluate at position i 32 | for (int j = 0; j < (int) cur.size(); ++j) 33 | t = (t + 1 LL * x[i - j - 1] * cur[j]) % mod; 34 | 35 | if ((t - x[i]) % mod == 0) continue; 36 | 37 | if (!cur.size()) { //first non-zero element 38 | cur.resize(i + 1); 39 | lf = i; 40 | ld = (t - x[i]) % mod; 41 | continue; 42 | } 43 | int k = 1 LL * (t - x[i]) * pw(ld, mod - 2) % mod; 44 | vector < int > c(i - lf - 1); //add zeroes in front 45 | c.push_back(k); //add '1' 46 | for (int j = 0; j < (int) ls.size(); ++j) //add minus previous s' 47 | c.push_back(-1 LL * ls[j] * k % mod); 48 | 49 | if (c.size() < cur.size()) c.resize(cur.size()); 50 | 51 | for (int j = 0; j < (int) cur.size(); ++j) 52 | c[j] = (c[j] + cur[j]) % mod; 53 | 54 | if (i + lf + (int) ls.size() >= (int) cur.size()) 55 | ls = cur, lf = i, ld = (t - x[i]) % mod; 56 | cur = c; 57 | } 58 | for (int i = 0; i < (int) cur.size(); ++i) 59 | cur[i] = (cur[i] % mod + mod) % mod; 60 | 61 | m = cur.size(); 62 | p.resize(m), a.resize(m); 63 | for (int i = 0; i < m; ++i) 64 | p[i] = cur[i], a[i] = x[i]; 65 | return cur; 66 | } 67 | 68 | inline vector < int > mul(vector < int > & a, vector < int > & b) { // a * b mod f; f = x ** m - sum{1..m} x**(m-j) * pj 69 | //may be optimized using FFT, NTT 70 | vector < int > r(2 * m); 71 | for (int i = 0; i < m; ++i) 72 | if (a[i]) 73 | for (int j = 0; j < m; ++j) 74 | r[i + j] = (r[i + j] + 1 LL * a[i] * b[j]) % mod; 75 | 76 | for (int i = 2 * m - 1; i >= m; --i) 77 | if (r[i]) 78 | for (int j = m - 1; j >= 0; --j) 79 | r[i - j - 1] = (r[i - j - 1] + 1 LL * p[j] * r[i]) % mod; 80 | 81 | r.resize(m); 82 | return r; 83 | } 84 | // O(m*m*log(k)) with Fourier O(m*log(m)*log(k)) 85 | inline int calc(long long k) { // res = G[ x**k ] = G[ x ** k mod f] 86 | if (m == 0) return 0; 87 | vector < int > bs(m), r(m); 88 | 89 | if (m == 1) bs[0] = p[0]; 90 | else bs[1] = 1; 91 | 92 | r[0] = 1; 93 | 94 | while (k) { 95 | if (k & 1) r = mul(r, bs); 96 | bs = mul(bs, bs); 97 | k >>= 1; 98 | } 99 | int res = 0; 100 | for (int i = 0; i < m; ++i) 101 | res = (res + 1 LL * r[i] * a[i]) % mod; 102 | return res; 103 | } 104 | } -------------------------------------------------------------------------------- /Math/Chinese remainder theorem.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: |N|*log(|N|) 2 | /// Tested: Not yet. 3 | /// finds a suitable x that meets: x is congruent to a_i mod n_i 4 | /** Works for non-coprime moduli. 5 | Returns {-1,-1} if solution does not exist or input is invalid. 6 | Otherwise, returns {x,L}, where x is the solution unique to mod L = LCM of mods 7 | */ 8 | pair chinese_remainder_theorem( vector A, vector M ) { 9 | int n = A.size(), a1 = A[0], m1 = M[0]; 10 | for(int i = 1; i < n; i++) { 11 | int a2 = A[i], m2 = M[i]; 12 | int g = __gcd(m1, m2); 13 | if( a1 % g != a2 % g ) return {-1,-1}; 14 | int p, q; 15 | eea(m1/g, m2/g, &p, &q); 16 | int mod = m1 / g * m2; 17 | q %= mod; p %= mod; 18 | int x = ((1ll*(a1%mod)*(m2/g))%mod*q + (1ll*(a2%mod)*(m1/g))%mod*p) % mod; // if WA there is overflow 19 | a1 = x; 20 | if (a1 < 0) a1 += mod; 21 | m1 = mod; 22 | } 23 | return {a1, m1}; 24 | } 25 | -------------------------------------------------------------------------------- /Math/Constant modular inverse.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|P|) 2 | /// Tested: not yet 3 | /// Find the multiplicative inverse of all 2<=i 1) 16 | return -1; 17 | return (x % n + n) % n; 18 | } 19 | -------------------------------------------------------------------------------- /Math/Fast Fourier transform module.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log(|N|)) 2 | /// Tested: https://tinyurl.com/yagvw3on 3 | const int mod = 7340033; /// mod = c*2^k+1 4 | /// find g = primitive root of mod. 5 | const int root = 2187; /// (g^c)%mod 6 | const int root_1 = 4665133; /// inverse of root 7 | const int root_pw = 1 << 19; /// 2^k 8 | 9 | pii find_c_k(int mod) { 10 | pii ans; 11 | for(int k = 1; (1< seen(mod); 21 | for(int r = 2; ; r++) { 22 | fill(seen.begin(), seen.end(), 0); 23 | int cur = 1, can = 1; 24 | for(int i = 0; i <= mod-2 && can; i++) { 25 | if(seen[cur]) can = 0; 26 | seen[cur] = 1; 27 | cur = (1ll*cur*r) % mod; 28 | } 29 | if(can) 30 | return r; 31 | } 32 | assert(false); 33 | } 34 | 35 | void fft(vector &a, bool inv = 0) { 36 | int n = a.size(); 37 | for(int i = 1, j = 0; i < n; i++) { 38 | int c = n >> 1; 39 | for (; j >= c; c >>= 1) j -= c; 40 | j += c; 41 | if(i < j) swap(a[i], a[j]); 42 | } 43 | for (int len = 2; len <= n; len <<= 1) { 44 | int wlen = inv ? root_1 : root; 45 | for(int i = len; i < root_pw; i <<= 1) wlen = (1 LL * wlen * wlen) % mod; 46 | for(int i = 0; i < n; i += len) { 47 | int w = 1; 48 | for(int j = 0; j < (len >> 1); j++) { 49 | int u = a[i + j], v = (a[i + j + (len >> 1)] * 1 LL * w) % mod; 50 | a[i + j] = u + v < mod ? u + v : u + v - mod; 51 | a[i + j + (len >> 1)] = u - v >= 0 ? u - v : u - v + mod; 52 | w = (w * 1 LL * wlen) % mod; 53 | } 54 | } 55 | } 56 | if (inv) { 57 | int nrev = pow(n); 58 | for(int i = 0; i < n; i++) a[i] = (a[i] * 1 LL * nrev) % mod; 59 | } 60 | } 61 | vector mul(const vector a, const vector b) { 62 | vector fa(a.begin(), a.end()), fb(b.begin(), b.end()); 63 | int n = 1; 64 | while (n < max(a.size(), b.size())) n <<= 1; 65 | n <<= 1; 66 | fa.resize(n); fb.resize(n); 67 | fft(fa); fft(fb); 68 | for (int i = 0; i < n; i++) fa[i] = (1ll * fa[i] * fb[i]) % mod; 69 | fft(fa, 1); 70 | return fa; 71 | } 72 | -------------------------------------------------------------------------------- /Math/Fast fourier transform.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log(|N|)) 2 | /// Tested: https://tinyurl.com/y8g2q66b 3 | namespace fft { 4 | typedef long long ll; 5 | const double PI = acos(-1.0); 6 | vector rev; 7 | struct pt { 8 | double r, i; 9 | pt(double r = 0.0, double i = 0.0) : r(r), i(i) {} 10 | pt operator + (const pt & b) { return pt(r + b.r, i + b.i); } 11 | pt operator - (const pt & b) { return pt(r - b.r, i - b.i); } 12 | pt operator * (const pt & b) { return pt(r * b.r - i * b.i, r * b.i + i * b.r); } 13 | }; 14 | void fft(vector &y, int on) { 15 | int n = y.size(); 16 | for(int i = 1; i < n; i++) if(i < rev[i]) swap(y[i], y[rev[i]]); 17 | for(int m = 2; m <= n; m <<= 1) { 18 | pt wm(cos(-on * 2 * PI / m), sin(-on * 2 * PI / m)); 19 | for(int k = 0; k < n; k += m) { 20 | pt w(1, 0); 21 | for(int j = 0; j < m / 2; j++) { 22 | pt u = y[k + j]; 23 | pt t = w * y[k + j + m / 2]; 24 | y[k + j] = u + t; 25 | y[k + j + m / 2] = u - t; 26 | w = w * wm; 27 | } 28 | } 29 | } 30 | if(on == -1) 31 | for(int i = 0; i < n; i++) y[i].r /= n; 32 | } 33 | vector mul(vector &a, vector &b) { 34 | int n = 1, la = a.size(), lb = b.size(), t; 35 | for(n = 1, t = 0; n <= (la+lb+1); n <<= 1, t++); t = 1<<(t-1); 36 | vector x1(n), x2(n); 37 | rev.assign(n, 0); 38 | for(int i = 0; i < n; i++) rev[i] = rev[i >> 1] >> 1 |(i & 1 ? t : 0); 39 | for(int i = 0; i < la; i++) x1[i] = pt(a[i], 0); 40 | for(int i = 0; i < lb; i++) x2[i] = pt(b[i], 0); 41 | fft(x1, 1); fft(x2, 1); 42 | for(int i = 0; i < n; i++) x1[i] = x1[i] * x2[i]; 43 | fft(x1, -1); 44 | vector sol(n); 45 | for(int i = 0; i < n; i++) sol[i] = x1[i].r + 0.5; 46 | return sol; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Math/Gauss jordan.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|^3) 2 | /// Tested: https://tinyurl.com/y23sh38k 3 | const int EPS = 1; 4 | int gauss (vector> a, vector &ans) { 5 | int n = a.size(), m = a[0].size()-1; 6 | vector where(m, -1); 7 | for(int col = 0, row = 0; col < m && row < n; ++col) { 8 | int sel = row; 9 | for(int i = row; i < n; ++i) 10 | if(abs(a[i][col]) > abs(a[sel][col])) sel = i; 11 | if(abs(a[sel][col]) < EPS) continue; 12 | swap(a[sel], a[row]); 13 | where[col] = row; 14 | for(int i = 0; i < n; ++i) 15 | if(i != row) { 16 | int c = divide(a[i][col], a[row][col]); /// precalc inverses 17 | for(int j = col; j <= m; ++j) 18 | a[i][j] = sub(a[i][j], mul(a[row][j], c)); 19 | } 20 | ++row; 21 | } 22 | ans.assign(m, 0); 23 | for(int i = 0; i < m; ++i) 24 | if(where[i] != -1) ans[i] = divide(a[where[i]][m], a[where[i]][i]); 25 | for(int i = 0; i < n; ++i) { 26 | int sum = 0; 27 | for(int j = 0; j < m; ++j) 28 | sum = add(sum, mul(ans[j], a[i][j])); 29 | if(sum != a[i][m]) return 0; 30 | } 31 | for(int i = 0; i < m; ++i) 32 | if(where[i] == -1) return -1; /// infinite solutions 33 | return 1; 34 | } 35 | -------------------------------------------------------------------------------- /Math/Integral.tex: -------------------------------------------------------------------------------- 1 | \begin{itemize} 2 | \item Simpsons rule: $\int_{a}^{b}f(x)dx \approx \frac{b-a}{6}[f(a)+4f(\frac{a+b}{2})+f(b)]$ 3 | 4 | \item Arc length: $s = \int_{a}^{b}\sqrt{1+[f'(x)]^{2}}dx$ 5 | 6 | \item Area of a surface of revolution: $A = 2\pi \int_{a}^{b}f(x)\sqrt{1+[f'(x)]^{2}}dx $ 7 | 8 | \item Volume of a solid of revolution: $V = \pi \int_{a}^{b}f(x)^{2}dx$ 9 | 10 | \item Note: In case of multiple functions such as \textit{g(x)} \textit{h(x)} for a solid of revolution then $f(x)=g(x)-h(x)$ 11 | 12 | \item $f'(x)\approx \frac{f(x+h)-f(x-h)}{2h}$ 13 | 14 | \item $f'(x)\approx \frac{f(x-2h)-8f(x-h)+8f(x+h)-f(x+2h)}{12h}$ 15 | 16 | \item $f''(x)\approx \frac{f(x+h)-2f(x)+f(x-h)}{h^{2}}$ 17 | \end{itemize} 18 | -------------------------------------------------------------------------------- /Math/Lagrange Interpolation.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|^2) 2 | /// Tested: https://tinyurl.com/y23sh38k 3 | vector X, F; 4 | lf f(lf x) { 5 | lf answer = 0; 6 | for(int i = 0; i < (int)X.size(); i++) { 7 | lf prod = F[i]; 8 | for(int j = 0; j < (int)X.size(); j++) { 9 | if(i == j) continue; 10 | prod = mul(prod, divide(sub(x, X[j]), sub(X[i], X[j]))); 11 | } 12 | answer = add(answer, prod); 13 | } 14 | return answer; 15 | } 16 | -------------------------------------------------------------------------------- /Math/Linear diophantine.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(log(|N|)) 2 | /// Tested: https://tinyurl.com/y8yc52gv 3 | bool diophantine(ll a, ll b, ll c, ll &x, ll &y, ll &g) { 4 | x = y = 0; 5 | if(a == 0 && b == 0) return c == 0; 6 | if(b == 0) swap(a, b), swap(x, y); 7 | g = eea(abs(a), abs(b), x, y); 8 | if(c % g) return false; 9 | a /= g; b /= g; c /= g; 10 | if(a < 0) x *= -1; 11 | x = (x % b) * (c % b) % b; 12 | if(x < 0) x += b; 13 | y = (c - a*x) / b; 14 | return true; 15 | } 16 | ///finds the first k | x + b * k / gcd(a, b) >= val 17 | ll greater_or_equal_than(ll a, ll b, ll x, ll val, ll g) { 18 | lf got = 1.0 * (val - x) * g / b; 19 | return b > 0 ? ceil(got) : floor(got); 20 | } 21 | void get_xy (ll a, ll b, ll &x, ll &y, ll k, ll g) { /// if for y, change the order to b,a y,x 22 | x = x + b / g * k; 23 | y = y - a / g * k; 24 | } 25 | -------------------------------------------------------------------------------- /Math/Matrix multiplication.cpp: -------------------------------------------------------------------------------- 1 | const int MOD = 1e9+7; 2 | struct matrix { 3 | const int N = 2; 4 | int m[N][N], r, c; 5 | matrix(int r = N, int c = N, bool iden = false) : r(r), c(c) { 6 | memset(m, 0, sizeof m); 7 | if(iden) 8 | for(int i = 0; i < r; i++) m[i][i] = 1; 9 | } 10 | matrix operator * (const matrix &o) const { 11 | matrix ret(r, o.c); 12 | for(int i = 0; i < r; ++i) 13 | for(int j = 0; j < o.c; ++j) { 14 | ll &r = ret.m[i][j]; 15 | for(int k = 0; k < c; ++k) 16 | r = (r + 1ll*m[i][k]*o.m[k][j]) % MOD; 17 | } 18 | return ret; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /Math/Miller rabin.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: ??? 2 | /// Tested: A lot.. but no link 3 | ll mul (ll a, ll b, ll mod) { 4 | ll ret = 0; 5 | for(a %= mod, b %= mod; b != 0; 6 | b >>= 1, a <<= 1, a = a >= mod ? a - mod : a) { 7 | if (b & 1) { 8 | ret += a; 9 | if (ret >= mod) ret -= mod; 10 | } 11 | } 12 | return ret; 13 | } 14 | ll fpow (ll a, ll b, ll mod) { 15 | ll ans = 1; 16 | for (; b; b >>= 1, a = mul(a, a, mod)) 17 | if (b & 1) 18 | ans = mul(ans, a, mod); 19 | return ans; 20 | } 21 | bool witness (ll a, ll s, ll d, ll n) { 22 | ll x = fpow(a, d, n); 23 | if (x == 1 || x == n - 1) return false; 24 | for (int i = 0; i < s - 1; i++) { 25 | x = mul(x, x, n); 26 | if (x == 1) return true; 27 | if (x == n - 1) return false; 28 | } 29 | return true; 30 | } 31 | ll test[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 0}; 32 | bool is_prime (ll n) { 33 | if (n < 2) return false; 34 | if (n == 2) return true; 35 | if (n % 2 == 0) return false; 36 | ll d = n - 1, s = 0; 37 | while (d % 2 == 0) ++s, d /= 2; 38 | for (int i = 0; test[i] && test[i] < n; ++i) 39 | if (witness(test[i], s, d, n)) 40 | return false; 41 | return true; 42 | } 43 | -------------------------------------------------------------------------------- /Math/Pollard's rho.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: ??? 2 | /// Tested: Not yet 3 | ll pollard_rho(ll n, ll c) { 4 | ll x = 2, y = 2, i = 1, k = 2, d; 5 | while (true) { 6 | x = (mul(x, x, n) + c); 7 | if (x >= n) x -= n; 8 | d = __gcd(x - y, n); 9 | if (d > 1) return d; 10 | if (++i == k) y = x, k <<= 1; 11 | } 12 | return n; 13 | } 14 | void factorize(ll n, vector &f) { 15 | if (n == 1) return; 16 | if (is_prime(n)) { 17 | f.push_back(n); 18 | return; 19 | } 20 | ll d = n; 21 | for (int i = 2; d == n; i++) 22 | d = pollard_rho(n, i); 23 | factorize(d, f); 24 | factorize(n/d, f); 25 | } 26 | -------------------------------------------------------------------------------- /Math/Simplex.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|^2 * |M|) N variables, N restrictions 2 | /// Tested: https://tinyurl.com/ybphh57p 3 | const double EPS = 1e-6; 4 | typedef vector vec; 5 | namespace simplex { 6 | vector X, Y; 7 | vector a; 8 | vec b, c; 9 | double z; 10 | int n, m; 11 | void pivot(int x, int y) { 12 | swap(X[y], Y[x]); 13 | b[x] /= a[x][y]; 14 | for(int i = 0; i < m; i++) 15 | if(i != y) 16 | a[x][i] /= a[x][y]; 17 | a[x][y] = 1 / a[x][y]; 18 | for(int i = 0; i < n; i++) 19 | if(i != x && abs(a[i][y]) > EPS) { 20 | b[i] -= a[i][y] * b[x]; 21 | for(int j = 0; j < m; j++) 22 | if(j != y) 23 | a[i][j] -= a[i][y] * a[x][j]; 24 | a[i][y] =- a[i][y] * a[x][y]; 25 | } 26 | z += c[y] * b[x]; 27 | for(int i = 0; i < m; i++) 28 | if(i != y) 29 | c[i] -= c[y] * a[x][i]; 30 | c[y] =- c[y] * a[x][y]; 31 | } 32 | /// A is a vector of 1 and 0. B is the limit restriction. C is the factors of O.F. 33 | pair simplex(vector &A, vec &B, vec &C) { 34 | a = A; b = B; c = C; 35 | n = b.size(); m = c.size(); z = 0.0; 36 | X = vector(m); 37 | Y = vector(n); 38 | for(int i = 0; i < m; i++) X[i] = i; 39 | for(int i = 0; i < n; i++) Y[i] = i + m; 40 | while(1) { 41 | int x = -1, y = -1; 42 | double mn = -EPS; 43 | for(int i = 0; i < n; i++) 44 | if(b[i] < mn) 45 | mn = b[i], x = i; 46 | if(x < 0) break; 47 | for(int i = 0; i < m; i++) 48 | if(a[x][i] < -EPS) { y = i; break; } 49 | assert(y >= 0); // no sol 50 | pivot(x, y); 51 | } 52 | while(1) { 53 | double mx = EPS; 54 | int x = -1,y = -1; 55 | for(int i = 0; i < m; i++) 56 | if(c[i] > mx) 57 | mx = c[i], y = i; 58 | if(y < 0) break; 59 | double mn = 1e200; 60 | for(int i = 0; i < n; i++) 61 | if(a[i][y] > EPS && b[i] / a[i][y] < mn) 62 | mn = b[i] / a[i][y], x = i; 63 | assert(x >= 0); // unbound 64 | pivot(x, y); 65 | } 66 | vec r(m); 67 | for(int i = 0; i < n; i++) 68 | if(Y[i] < m) 69 | r[ Y[i] ] = b[i]; 70 | return make_pair(z, r); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Math/Simpson.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: ????? 2 | /// Tested: Not yet 3 | inline lf simpson(lf fl, lf fr, lf fmid, lf l, lf r) { 4 | return (fl + fr + 4.0 * fmid) * (r - l) / 6.0; 5 | } 6 | lf rsimpson (lf slr, lf fl, lf fr, lf fmid, lf l, lf r) { 7 | lf mid = (l + r) * 0.5; 8 | lf fml = f((l + mid) * 0.5); 9 | lf fmr = f((mid + r) * 0.5); 10 | lf slm = simpson(fl, fmid, fml, l, mid); 11 | lf smr = simpson(fmid, fr, fmr, mid, r); 12 | if (fabs(slr - slm - smr) < eps) return slm + smr; 13 | return rsimpson(slm, fl, fmid, fml, l, mid) + rsimpson(smr, fmid, fr, fmr, mid, r); 14 | } 15 | lf integrate(lf l,lf r) { 16 | lf mid = (l + r) * .5, fl = f(l), fr = f(r), fmid = f(mid); 17 | return rsimpson(simpson(fl, fr, fmid, l, r), fl, fr, fmid, l, r); 18 | } 19 | -------------------------------------------------------------------------------- /Math/Totient and divisors.cpp: -------------------------------------------------------------------------------- 1 | vector count_divisors_sieve() { 2 | bitset is_prime; is_prime.set(); 3 | vector cnt(mx, 1); 4 | is_prime[0] = is_prime[1] = 0; 5 | for(int i = 2; i < mx; i++) { 6 | if(!is_prime[i]) continue; 7 | cnt[i]++; 8 | for(int j = i+i; j < mx; j += i) { 9 | int n = j, c = 1; 10 | while( n%i == 0 ) n /= i, c++; 11 | cnt[j] *= c; 12 | is_prime[j] = 0; 13 | } 14 | } 15 | return cnt; 16 | } 17 | vector euler_phi_sieve() { 18 | bitset is_prime; is_prime.set(); 19 | vector phi(mx); 20 | iota(phi.begin(), phi.end(), 0); 21 | is_prime[0] = is_prime[1] = 0; 22 | for(int i = 2; i < mx; i++) { 23 | if(!is_prime[i]) continue; 24 | for(int j = i; j < mx; j += i) { 25 | phi[j] -= phi[j]/i; 26 | is_prime[j] = 0; 27 | } 28 | } 29 | return phi; 30 | } 31 | ll euler_phi(ll n) { 32 | ll ans = n; 33 | for(ll i = 2; i * i <= n; ++i) { 34 | if(n % i == 0) { 35 | ans -= ans / i; 36 | while(n % i == 0) n /= i; 37 | } 38 | } 39 | if(n > 1) ans -= ans / n; 40 | return ans; 41 | } 42 | -------------------------------------------------------------------------------- /Network flows/Blossom.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|E||V|^2) 2 | /// Tested: https://tinyurl.com/oe5rnpk 3 | struct network { 4 | struct struct_edge { int v; struct_edge * n; }; 5 | typedef struct_edge* edge; 6 | int n; 7 | struct_edge pool[MAXE]; ///2*n*n; 8 | edge top; 9 | vector adj; 10 | queue q; 11 | vector f, base, inq, inb, inp, match; 12 | vector> ed; 13 | network(int n) : n(n), match(n, -1), adj(n), top(pool), f(n), base(n), 14 | inq(n), inb(n), inp(n), ed(n, vector(n)) {} 15 | void add_edge(int u, int v) { 16 | if(ed[u][v]) return; 17 | ed[u][v] = 1; 18 | top->v = v, top->n = adj[u], adj[u] = top++; 19 | top->v = u, top->n = adj[v], adj[v] = top++; 20 | } 21 | int get_lca(int root, int u, int v) { 22 | fill(inp.begin(), inp.end(), 0); 23 | while(1) { 24 | inp[u = base[u]] = 1; 25 | if(u == root) break; 26 | u = f[ match[u] ]; 27 | } 28 | while(1) { 29 | if(inp[v = base[v]]) return v; 30 | else v = f[ match[v] ]; 31 | } 32 | } 33 | void mark(int lca, int u) { 34 | while(base[u] != lca) { 35 | int v = match[u]; 36 | inb[ base[u ]] = 1; 37 | inb[ base[v] ] = 1; 38 | u = f[v]; 39 | if(base[u] != lca) f[u] = v; 40 | } 41 | } 42 | void blossom_contraction(int s, int u, int v) { 43 | int lca = get_lca(s, u, v); 44 | fill(inb.begin(), inb.end(), 0); 45 | mark(lca, u); mark(lca, v); 46 | if(base[u] != lca) f[u] = v; 47 | if(base[v] != lca) f[v] = u; 48 | for(int u = 0; u < n; u++) 49 | if(inb[base[u]]) { 50 | base[u] = lca; 51 | if(!inq[u]) { 52 | inq[u] = 1; 53 | q.push(u); 54 | } 55 | } 56 | } 57 | int bfs(int s) { 58 | fill(inq.begin(), inq.end(), 0); 59 | fill(f.begin(), f.end(), -1); 60 | for(int i = 0; i < n; i++) base[i] = i; 61 | q = queue(); 62 | q.push(s); 63 | inq[s] = 1; 64 | while(q.size()) { 65 | int u = q.front(); q.pop(); 66 | for(edge e = adj[u]; e; e = e->n) { 67 | int v = e->v; 68 | if(base[u] != base[v] && match[u] != v) { 69 | if((v == s) || (match[v] != -1 && f[match[v]] != -1)) 70 | blossom_contraction(s, u, v); 71 | else if(f[v] == -1) { 72 | f[v] = u; 73 | if(match[v] == -1) return v; 74 | else if(!inq[match[v]]) { 75 | inq[match[v]] = 1; 76 | q.push(match[v]); 77 | } 78 | } 79 | } 80 | } 81 | } 82 | return -1; 83 | } 84 | int doit(int u) { 85 | if(u == -1) return 0; 86 | int v = f[u]; 87 | doit(match[v]); 88 | match[v] = u; match[u] = v; 89 | return u != -1; 90 | } 91 | /// (i < net.match[i]) => means match 92 | int maximum_matching() { 93 | int ans = 0; 94 | for(int u = 0; u < n; u++) 95 | ans += (match[u] == -1) && doit(bfs(u)); 96 | return ans; 97 | } 98 | }; 99 | -------------------------------------------------------------------------------- /Network flows/Dinic.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|E|*|V|^2) 2 | /// Tested: https://tinyurl.com/ya9rgoyk 3 | struct edge { int v, cap, inv, flow; }; 4 | struct network { 5 | int n, s, t; 6 | vector lvl; 7 | vector> g; 8 | network(int n) : n(n), lvl(n), g(n) {} 9 | void add_edge(int u, int v, int c) { 10 | g[u].push_back({v, c, g[v].size(), 0}); 11 | g[v].push_back({u, 0, g[u].size()-1, c}); 12 | } 13 | bool bfs() { 14 | fill(lvl.begin(), lvl.end(), -1); 15 | queue q; 16 | lvl[s] = 0; 17 | for(q.push(s); q.size(); q.pop()) { 18 | int u = q.front(); 19 | for(auto &e : g[u]) { 20 | if(e.cap > 0 && lvl[e.v] == -1) { 21 | lvl[e.v] = lvl[u]+1; 22 | q.push(e.v); 23 | } 24 | } 25 | } 26 | return lvl[t] != -1; 27 | } 28 | int dfs(int u, int nf) { 29 | if(u == t) return nf; 30 | int res = 0; 31 | for(auto &e : g[u]) { 32 | if(e.cap > 0 && lvl[e.v] == lvl[u]+1) { 33 | int tf = dfs(e.v, min(nf, e.cap)); 34 | res += tf; nf -= tf; e.cap -= tf; 35 | g[e.v][e.inv].cap += tf; 36 | g[e.v][e.inv].flow -= tf; 37 | e.flow += tf; 38 | if(nf == 0) return res; 39 | } 40 | } 41 | if(!res) lvl[u] = -1; 42 | return res; 43 | } 44 | int max_flow(int so, int si, int res = 0) { 45 | s = so; t = si; 46 | while(bfs()) res += dfs(s, INT_MAX); 47 | return res; 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /Network flows/Hopcroft karp.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|E|*sqrt(|V|)) 2 | /// Tested: https://tinyurl.com/yad2g9g9 3 | struct mbm { 4 | vector> g; 5 | vector d, match; 6 | int nil, l, r; 7 | /// u -> 0 to l, v -> 0 to r 8 | mbm(int l, int r) : l(l), r(r), nil(l+r), g(l+r), 9 | d(1+l+r, INF), match(l+r, l+r) {} 10 | void add_edge(int a, int b) { 11 | g[a].push_back(l+b); 12 | g[l+b].push_back(a); 13 | } 14 | bool bfs() { 15 | queue q; 16 | for(int u = 0; u < l; u++) { 17 | if(match[u] == nil) { 18 | d[u] = 0; 19 | q.push(u); 20 | } else d[u] = INF; 21 | } 22 | d[nil] = INF; 23 | while(q.size()) { 24 | int u = q.front(); q.pop(); 25 | if(u == nil) continue; 26 | for(auto v : g[u]) { 27 | if(d[ match[v] ] == INF) { 28 | d[ match[v] ] = d[u]+1; 29 | q.push(match[v]); 30 | } 31 | } 32 | } 33 | return d[nil] != INF; 34 | } 35 | bool dfs(int u) { 36 | if(u == nil) return true; 37 | for(int v : g[u]) { 38 | if(d[ match[v] ] == d[u]+1 && dfs(match[v])) { 39 | match[v] = u; match[u] = v; 40 | return true; 41 | } 42 | } 43 | d[u] = INF; 44 | return false; 45 | } 46 | int max_matching() { 47 | int ans = 0; 48 | while(bfs()) { 49 | for(int u = 0; u < l; u++) { 50 | ans += (match[u] == nil && dfs(u)); 51 | } 52 | } 53 | return ans; 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /Network flows/Maximum bipartite matching.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|E|*|V|) 2 | /// Tested: https://tinyurl.com/yad2g9g9 3 | struct mbm { 4 | int l, r; 5 | vector> g; 6 | vector match, seen; 7 | mbm(int l, int r) : l(l), r(r), seen(r), match(r), g(l) {} 8 | void add_edge(int l, int r) { g[l].push_back(r); } 9 | bool dfs(int u) { 10 | for(auto v : g[u]) { 11 | if(seen[v]++) continue; 12 | if(match[v] == -1 || dfs(match[v])) { 13 | match[v] = u; 14 | return true; 15 | } 16 | } 17 | return false; 18 | } 19 | int max_matching() { 20 | int ans = 0; 21 | fill(match.begin(), match.end(), -1); 22 | for(int u = 0; u < l; ++u) { 23 | fill(seen.begin(), seen.end(), 0); 24 | ans += dfs(u); 25 | } 26 | return ans; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /Network flows/Maximum flow minimum cost.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|V|*|E|^2*log(|E|)) 2 | /// Tested: https://tinyurl.com/ycgpp47z 3 | template 4 | struct mcmf { 5 | struct edge { int u, v, cap, flow; type cost; }; 6 | int n; 7 | vector ed; 8 | vector> g; 9 | vector p; 10 | vector d, phi; 11 | mcmf(int n) : n(n), g(n), p(n), d(n), phi(n) {} 12 | void add_edge(int u, int v, int cap, type cost) { 13 | g[u].push_back(ed.size()); 14 | ed.push_back({u, v, cap, 0, cost}); 15 | g[v].push_back(ed.size()); 16 | ed.push_back({v, u, 0, 0, -cost}); 17 | } 18 | bool dijkstra(int s, int t) { 19 | fill(d.begin(), d.end(), INF); 20 | fill(p.begin(), p.end(), -1); 21 | set> q; 22 | d[s] = 0; 23 | for(q.insert({d[s], s}); q.size();) { 24 | int u = (*q.begin()).second; q.erase(q.begin()); 25 | for(auto v : g[u]) { 26 | auto &e = ed[v]; 27 | type nd = d[e.u]+e.cost+phi[e.u]-phi[e.v]; 28 | if(0 < (e.cap-e.flow) && nd < d[e.v]) { 29 | q.erase({d[e.v], e.v}); 30 | d[e.v] = nd; p[e.v] = v; 31 | q.insert({d[e.v], e.v}); 32 | } 33 | } 34 | } 35 | for(int i = 0; i < n; i++) phi[i] = min(INF, phi[i]+d[i]); 36 | return d[t] != INF; 37 | } 38 | pair max_flow(int s, int t) { 39 | type mc = 0; 40 | int mf = 0; 41 | fill(phi.begin(), phi.end(), 0); 42 | while(dijkstra(s, t)) { 43 | int flow = INF; 44 | for(int v = p[t]; v != -1; v = p[ ed[v].u ]) 45 | flow = min(flow, ed[v].cap-ed[v].flow); 46 | for(int v = p[t]; v != -1; v = p[ ed[v].u ]) { 47 | edge &e1 = ed[v]; 48 | edge &e2 = ed[v^1]; 49 | mc += e1.cost*flow; 50 | e1.flow += flow; 51 | e2.flow -= flow; 52 | } 53 | mf += flow; 54 | } 55 | return {mf, mc}; 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /Network flows/Stoer Wagner.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|V|^3) 2 | /// Tested: https://tinyurl.com/y8eu433d 3 | struct stoer_wagner { 4 | int n; 5 | vector> g; 6 | stoer_wagner(int n) : n(n), g(n, vector(n)) {} 7 | void add_edge(int a, int b, int w) { g[a][b] = g[b][a] = w; } 8 | pair> min_cut() { 9 | vector used(n); 10 | vector cut, best_cut; 11 | int best_weight = -1; 12 | for(int p = n-1; p >= 0; --p) { 13 | vector w = g[0]; 14 | vector added = used; 15 | int prv, lst = 0; 16 | for(int i = 0; i < p; ++i) { 17 | prv = lst; lst = -1; 18 | for(int j = 1; j < n; ++j) 19 | if(!added[j] && (lst == -1 || w[j] > w[lst])) 20 | lst = j; 21 | if(i == p-1) { 22 | for(int j = 0; j < n; j++) 23 | g[prv][j] += g[lst][j]; 24 | for(int j = 0; j < n; j++) 25 | g[j][prv] = g[prv][j]; 26 | used[lst] = true; 27 | cut.push_back(lst); 28 | if(best_weight == -1 || w[lst] < best_weight) { 29 | best_cut = cut; 30 | best_weight = w[lst]; 31 | } 32 | } else { 33 | for(int j = 0; j < n; j++) 34 | w[j] += g[lst][j]; 35 | added[lst] = true; 36 | } 37 | } 38 | } 39 | return {best_weight, best_cut}; /// best_cut contains all nodes in the same set 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /Network flows/Weighted matching.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|V|^3) 2 | /// Tested: https://tinyurl.com/ycpq8eyl problem G 3 | typedef int type; 4 | struct matching_weighted { 5 | int l, r; 6 | vector> c; 7 | matching_weighted(int l, int r) : l(l), r(r), c(l, vector(r)) { 8 | assert(l <= r); 9 | } 10 | void add_edge(int a, int b, type cost) { c[a][b] = cost; } 11 | type matching() { 12 | vector v(r), d(r); // v: potential 13 | vector ml(l, -1), mr(r, -1); // matching pairs 14 | vector idx(r), prev(r); 15 | iota(idx.begin(), idx.end(), 0); 16 | auto residue = [&](int i, int j) { return c[i][j]-v[j]; }; 17 | for(int f = 0; f < l; ++f) { 18 | for(int j = 0; j < r; ++j) { 19 | d[j] = residue(f, j); 20 | prev[j] = f; 21 | } 22 | type w; 23 | int j, l; 24 | for (int s = 0, t = 0;;) { 25 | if(s == t) { 26 | l = s; 27 | w = d[ idx[t++] ]; 28 | for(int k = t; k < r; ++k) { 29 | j = idx[k]; 30 | type h = d[j]; 31 | if (h <= w) { 32 | if (h < w) t = s, w = h; 33 | idx[k] = idx[t]; 34 | idx[t++] = j; 35 | } 36 | } 37 | for (int k = s; k < t; ++k) { 38 | j = idx[k]; 39 | if (mr[j] < 0) goto aug; 40 | } 41 | } 42 | int q = idx[s++], i = mr[q]; 43 | for (int k = t; k < r; ++k) { 44 | j = idx[k]; 45 | type h = residue(i, j) - residue(i, q) + w; 46 | if (h < d[j]) { 47 | d[j] = h; 48 | prev[j] = i; 49 | if(h == w) { 50 | if(mr[j] < 0) goto aug; 51 | idx[k] = idx[t]; 52 | idx[t++] = j; 53 | } 54 | } 55 | } 56 | } 57 | aug: for (int k = 0; k < l; ++k) 58 | v[ idx[k] ] += d[ idx[k] ] - w; 59 | int i; 60 | do { 61 | mr[j] = i = prev[j]; 62 | swap(j, ml[i]); 63 | } while (i != f); 64 | } 65 | type opt = 0; 66 | for (int i = 0; i < l; ++i) 67 | opt += c[i][ml[i]]; // (i, ml[i]) is a solution 68 | return opt; 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /Strings/Aho corasick.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|text|+SUM(|pattern_i|)+matches) 2 | /// Tested: https://tinyurl.com/y2zq594p 3 | const static int alpha = 26; 4 | int trie[N][alpha], fail[N], nodes; 5 | void add(string &s, int i) { 6 | int cur = 0; 7 | for(char c : s) { 8 | int x = c-'a'; 9 | if(!trie[cur][x]) trie[cur][x] = ++nodes; 10 | cur = trie[cur][x]; 11 | } 12 | //cnt_word[cur]++; 13 | //end_word[cur] = i; // for i > 0 14 | } 15 | void build() { 16 | queue q; q.push(0); 17 | while(q.size()) { 18 | int u = q.front(); q.pop(); 19 | for(int i = 0; i < alpha; ++i) { 20 | int v = trie[u][i]; 21 | if(!v) trie[u][i] = trie[ fail[u] ][i]; // construir automata 22 | else q.push(v); 23 | if(!u || !v) continue; 24 | fail[v] = trie[ fail[u] ][i]; 25 | //fail_out[v] = end_word[ fail[v] ] ? fail[v] : fail_out[ fail[v] ]; 26 | //cnt_word[v] += cnt_word[ fail[v] ]; // obtener informacion del fail_padre 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Strings/Hashing.cpp: -------------------------------------------------------------------------------- 1 | /// Tested: https://tinyurl.com/y8qstx97 2 | /// 1000234999, 1000567999, 1000111997, 1000777121 3 | const int MODS[] = { 1001864327, 1001265673 }; 4 | const mint BASE(256, 256), ZERO(0, 0), ONE(1, 1); 5 | inline int add(int a, int b, const int& mod) { return a+b >= mod ? a+b-mod : a+b; } 6 | inline int sbt(int a, int b, const int& mod) { return a-b < 0 ? a-b+mod : a-b; } 7 | inline int mul(int a, int b, const int& mod) { return 1ll*a*b%mod; } 8 | inline ll operator ! (const mint a) { return (ll(a.first)<<32)|ll(a.second); } 9 | inline mint operator + (const mint a, const mint b) { 10 | return {add(a.first, b.first, MODS[0]), add(a.second, b.second, MODS[1])}; 11 | } 12 | inline mint operator - (const mint a, const mint b) { 13 | return {sbt(a.first, b.first, MODS[0]), sbt(a.second, b.second, MODS[1])}; 14 | } 15 | inline mint operator * (const mint a, const mint b) { 16 | return {mul(a.first, b.first, MODS[0]), mul(a.second, b.second, MODS[1])}; 17 | } 18 | mint base[MAXN]; 19 | void prepare() { 20 | base[0] = ONE; 21 | for(int i = 1; i < MAXN; i++) base[i] = base[i-1]*BASE; 22 | } 23 | template 24 | struct hashing { 25 | vector code; 26 | hashing(type &t) { 27 | code.resize(t.size()+1); 28 | code[0] = ZERO; 29 | for (int i = 1; i < code.size(); ++i) 30 | code[i] = code[i-1]*BASE + mint{t[i-1], t[i-1]}; 31 | } 32 | mint query(int l, int r) { 33 | return code[r+1] - code[l]*base[r-l+1]; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /Strings/Kmp automaton.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*alphabet) 2 | /// Tested: not yet 3 | const int alpha = 256; 4 | int aut[N][alpha]; 5 | void kmp_automaton(string &t) { 6 | aut[0][ t[0] ] = 1; 7 | for(int i = 1, j = 0; i <= t.size(); ++i) { 8 | for(int c = 0; c < alpha; ++c) aut[i][c] = aut[j][c]; 9 | if(i < t.size()) { 10 | aut[i][ t[i] ] = i+1; 11 | j = aut[j][ t[i] ]; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Strings/Kmp.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/y7svn3kr 3 | vector get_phi(string &p) { 4 | vector phi(p.size()); 5 | phi[0] = 0; 6 | for(int i = 1, j = 0; i < p.size(); ++i ) { 7 | while(j > 0 && p[i] != p[j] ) j = phi[j-1]; 8 | if(p[i] == p[j]) ++j; 9 | phi[i] = j; 10 | } 11 | return phi; 12 | } 13 | int get_match(string &t, string &p) { 14 | vector phi = get_phi(p); 15 | int matches = 0; 16 | for(int i = 0, j = 0; i < t.size(); ++i ) { 17 | while(j > 0 && t[i] != p[j] ) j = phi[j-1]; 18 | if(t[i] == p[j]) ++j; 19 | if(j == p.size()) { 20 | matches++; 21 | j = phi[j-1]; 22 | } 23 | } 24 | return matches; 25 | } 26 | -------------------------------------------------------------------------------- /Strings/Manacher.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/y6upxbpa 3 | ///to = i - from[i]; 4 | ///len = to - from[i] + 1 = i - 2 * from[i] + 1; 5 | vector manacher(string &s) { 6 | int n = s.size(), p = 0, pr = -1; 7 | vector from(2*n-1); 8 | for(int i = 0; i < 2*n-1; ++i) { 9 | int r = i <= 2*pr ? min(p - from[2*p - i], pr) : i/2; 10 | int l = i - r; 11 | while(l > 0 && r < n-1 && s[l-1] == s[r+1]) --l, ++r; 12 | from[i] = l; 13 | if (r > pr) { 14 | pr = r; 15 | p = i; 16 | } 17 | } 18 | return from; 19 | } 20 | -------------------------------------------------------------------------------- /Strings/Minimun expression.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/y6gfzgsm 3 | int minimum_expression(string s) { 4 | s = s+s; 5 | int len = s.size(), i = 0, j = 1, k = 0; 6 | while(i+k < len && j+k < len) { 7 | if(s[i+k] == s[j+k]) k++; 8 | else if(s[i+k] > s[j+k]) i = i+k+1, k = 0; 9 | else j = j+k+1, k = 0; 10 | if(i == j) j++; 11 | } 12 | return min(i, j); 13 | } 14 | -------------------------------------------------------------------------------- /Strings/Suffix array.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log(|N|)) 2 | /// Tested: https://tinyurl.com/y8wdubdw 3 | const int alpha = 400; 4 | struct suffix_array { // s MUST not have 0 value 5 | vector sa, pos, lcp; 6 | suffix_array(string s) { 7 | s.push_back('$'); // always add something less to input, so it stays in pos 0 8 | int n = s.size(), mx = max(alpha, n)+2; 9 | vector a(n+1), a1(n+1), c(2*n), c1(2*n), head(mx), cnt(mx); 10 | pos = lcp = a; 11 | for(int i = 0; i < n; i++) c[i] = s[i], a[i] = i, cnt[ c[i] ]++; 12 | for(int i = 0; i < mx-1; i++) head[i+1] = head[i] + cnt[i]; 13 | for(int k = 0; k < n; k = max(1, k<<1)) { 14 | for(int i = 0; i < n; i++) { 15 | int j = (a[i] - k + n) % n; 16 | a1[ head[ c[j] ]++ ] = j; 17 | } 18 | swap(a1, a); 19 | for(int i = 0, x = a[0], y, col = 0; i < n; i++, x = a[i], y = a[i-1]) { 20 | c1[x] = (i && c[x] == c[y] && c[x+k] == c[y+k]) ? col : ++col; 21 | if(!i || c1[x] != c1[y]) head[col] = i; 22 | } 23 | swap(c1, c); 24 | if(c[ a[n-1] ] == n) break; 25 | } 26 | swap(sa, a); 27 | for(int i = 0; i < n; i++) pos[ sa[i] ] = i; 28 | for(int i = 0, k = 0, j; i < n; lcp[ pos[i++] ] = k) { 29 | if(pos[i] == n-1) continue; 30 | for(k = max(0, k-1), j = sa[ pos[i]+1 ]; s[i+k] == s[j+k]; k++); 31 | } 32 | } 33 | int& operator[] ( int i ){ return sa[i]; } 34 | }; 35 | -------------------------------------------------------------------------------- /Strings/Suffix automaton.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|*log(|alphabet|)) 2 | /// Tested: https://tinyurl.com/y7cevdeg 3 | struct suffix_automaton { 4 | struct node { 5 | int len, link; bool end; 6 | map next; 7 | }; 8 | vector sa; 9 | int last; 10 | suffix_automaton() {} 11 | suffix_automaton(string s) { 12 | sa.reserve(s.size()*2); 13 | last = add_node(); 14 | sa[last].len = 0; 15 | sa[last].link = -1; 16 | for(int i = 0; i < s.size(); ++i) 17 | sa_append(s[i]); 18 | ///t0 is not suffix 19 | for(int cur = last; cur; cur = sa[cur].link) 20 | sa[cur].end = 1; 21 | } 22 | int add_node() { 23 | sa.push_back({}); 24 | return sa.size()-1; 25 | } 26 | void sa_append(char c) { 27 | int cur = add_node(); 28 | sa[cur].len = sa[last].len + 1; 29 | int p = last; 30 | while(p != -1 && !sa[p].next[c] ){ 31 | sa[p].next[c] = cur; 32 | p = sa[p].link; 33 | } 34 | if(p == -1) sa[cur].link = 0; 35 | else { 36 | int q = sa[p].next[c]; 37 | if(sa[q].len == sa[p].len+1) sa[cur].link = q; 38 | else { 39 | int clone = add_node(); 40 | sa[clone] = sa[q]; 41 | sa[clone].len = sa[p].len+1; 42 | sa[q].link = sa[cur].link = clone; 43 | while(p != -1 && sa[p].next[c] == q) { 44 | sa[p].next[c] = clone; 45 | p = sa[p].link; 46 | } 47 | } 48 | } 49 | last = cur; 50 | } 51 | node& operator[](int i) { return sa[i]; } 52 | }; 53 | -------------------------------------------------------------------------------- /Strings/Z algorithm.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: O(|N|) 2 | /// Tested: https://tinyurl.com/yc3rjh4p 3 | vector z_algorithm (string s) { 4 | int n = s.size(); 5 | vector z(n); 6 | int x = 0, y = 0; 7 | for(int i = 1; i < n; ++i) { 8 | z[i] = max(0, min(z[i-x], y-i+1)); 9 | while (i+z[i] < n && s[z[i]] == s[i+z[i]]) 10 | x = i, y = i+z[i], z[i]++; 11 | } 12 | return z; 13 | } 14 | -------------------------------------------------------------------------------- /Utilities/Hash STL.cpp: -------------------------------------------------------------------------------- 1 | /// Complexity: - 2 | /// Tested: https://tinyurl.com/y8orp8t2 3 | struct Hash { 4 | size_t operator()(const pii &x) const { 5 | return (size_t) x.first * 37U + (size_t) x.second; 6 | } 7 | size_t operator()(const vector &v)const{ 8 | size_t s = 0; 9 | for(auto &e : v) 10 | s ^= hash()(e)+0x9e3779b9+(s<<6)+(s>>2); 11 | return s; 12 | } 13 | }; 14 | unordered_map mp; 15 | mp.reserve(1024); /// power of 2 16 | mp.max_load_factor(0.25); 17 | -------------------------------------------------------------------------------- /Utilities/Pragma optimizations.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC optimize ("O3") 2 | #pragma GCC target ("sse4") 3 | #pragma GCC target ("avx,tune=native") 4 | -------------------------------------------------------------------------------- /Utilities/Random.cpp: -------------------------------------------------------------------------------- 1 | // Declare number generator 2 | mt19937 / mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()) 3 | // or 4 | random_device rd 5 | mt19937 / mt19937_64 rng(rd()) 6 | 7 | // Use it to shuffle a vector 8 | shuffle(permutation.begin(), permutation.end(), rng) 9 | 10 | // Use it to generate a random number between [fr, to] 11 | uniform_int_distribution / uniform_real_distribution dis(fr, to); 12 | dis(rng) -------------------------------------------------------------------------------- /Utilities/template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define ff first 5 | #define ss second 6 | #define mp make_pair 7 | #define pb push_back 8 | 9 | typedef long long ll; 10 | typedef double lf; 11 | typedef pair pii; 12 | 13 | const int N = 1e5+10; 14 | const int oo = 1e9; 15 | 16 | int main () { 17 | ios::sync_with_stdio(0); 18 | cin.tie(0); 19 | #ifdef LOCAL 20 | freopen("input.txt", "r", stdin); 21 | #else 22 | #define endl '\n' 23 | #endif 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /Utilities/vimsrc.cpp: -------------------------------------------------------------------------------- 1 | //vimrc 2 | noremap :w !g++ -DLOCAL -std=c++14 -static -Wall -Wno-unused-result -O2 %:r.cpp -o %:r 3 | noremap :w !g++ -DLOCAL -std=c++14 -static -Wall -Wno-unused-result -O2 %:r.cpp -o %:r && ./%:r 4 | noremap : !./%:r 5 | set number 6 | set shiftwidth=2 7 | set tabstop=2 8 | set autoindent 9 | set expandtab 10 | //judge 11 | submit() { boca-submit-run TEAM PASSWORD "$1" C++14 "$1.cpp"; } 12 | -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavd09/notebook_unal/d46ba3a751d515c7b1e2f7cf0ad7b5451c4a5fe7/cover.png --------------------------------------------------------------------------------