├── README.md ├── data ├── dsu.cpp ├── fenwick.cpp ├── fenwick2d.cpp ├── segtree.cpp └── sparsetable.cpp ├── flows ├── blossom.cpp ├── dinic-edge-ids.cpp ├── dinic-old.cpp ├── dinic.cpp ├── fastflow-other.cpp ├── fastflow.cpp ├── flow_decomposition.cpp ├── flow_graph.cpp ├── gomory_hu-old.cpp ├── gomory_hu.cpp ├── hungarian-arrays.cpp ├── hungarian.cpp ├── matching.cpp └── mcmf.cpp ├── graph ├── bicone.cpp ├── biconv.cpp ├── bridges.cpp ├── cutpoints.cpp ├── cycles.cpp ├── dfs_digraph_useless.cpp ├── dfs_forest.cpp ├── dfs_undigraph.cpp ├── digraph.cpp ├── dijkstra-set.cpp ├── dijkstra.cpp ├── dominators.cpp ├── eulerian.cpp ├── forest.cpp ├── graph.cpp ├── hld_forest.cpp ├── lca_forest.cpp ├── mst.cpp ├── scc.cpp ├── topsort.cpp ├── twosat.cpp └── undigraph.cpp ├── misc ├── debug.cpp └── lis.cpp ├── numeric ├── bm.cpp ├── extgcd.cpp ├── factorizer.cpp ├── fft.cpp ├── fwht.cpp ├── md.cpp ├── mint.cpp ├── ntt.cpp ├── poly.cpp └── primitive.cpp ├── string ├── duval.cpp ├── duval_prefixes.cpp ├── kmp.cpp ├── manacher.cpp ├── suffix_array.cpp └── z.cpp └── todo.txt /README.md: -------------------------------------------------------------------------------- 1 | # algo -------------------------------------------------------------------------------- /data/dsu.cpp: -------------------------------------------------------------------------------- 1 | class dsu { 2 | public: 3 | vector<int> p; 4 | int n; 5 | 6 | dsu(int _n) : n(_n) { 7 | p.resize(n); 8 | iota(p.begin(), p.end(), 0); 9 | } 10 | 11 | inline int get(int x) { 12 | return (x == p[x] ? x : (p[x] = get(p[x]))); 13 | } 14 | 15 | inline bool unite(int x, int y) { 16 | x = get(x); 17 | y = get(y); 18 | if (x != y) { 19 | p[x] = y; 20 | return true; 21 | } 22 | return false; 23 | } 24 | }; -------------------------------------------------------------------------------- /data/fenwick.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class fenwick { 3 | public: 4 | vector<T> fenw; 5 | int n; 6 | 7 | fenwick(int _n) : n(_n) { 8 | fenw.resize(n); 9 | } 10 | 11 | void modify(int x, T v) { 12 | while (x < n) { 13 | fenw[x] += v; 14 | x |= (x + 1); 15 | } 16 | } 17 | 18 | T get(int x) { 19 | T v{}; 20 | while (x >= 0) { 21 | v += fenw[x]; 22 | x = (x & (x + 1)) - 1; 23 | } 24 | return v; 25 | } 26 | }; 27 | 28 | struct node { 29 | int a = ...; // don't forget to set default value 30 | 31 | inline void operator += (node &other) { 32 | ... 33 | } 34 | }; -------------------------------------------------------------------------------- /data/fenwick2d.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class fenwick2d { 3 | public: 4 | vector< vector<T> > fenw; 5 | int n, m; 6 | 7 | fenwick2d(int _n, int _m) : n(_n), m(_m) { 8 | fenw.resize(n); 9 | for (int i = 0; i < n; i++) { 10 | fenw[i].resize(m); 11 | } 12 | } 13 | 14 | inline void modify(int i, int j, T v) { 15 | int x = i; 16 | while (x < n) { 17 | int y = j; 18 | while (y < m) { 19 | fenw[x][y] += v; 20 | y |= (y + 1); 21 | } 22 | x |= (x + 1); 23 | } 24 | } 25 | 26 | inline T get(int i, int j) { 27 | T v{}; 28 | int x = i; 29 | while (x >= 0) { 30 | int y = j; 31 | while (y >= 0) { 32 | v += fenw[x][y]; 33 | y = (y & (y + 1)) - 1; 34 | } 35 | x = (x & (x + 1)) - 1; 36 | } 37 | return v; 38 | } 39 | }; 40 | 41 | struct node { 42 | int a = ...; // don't forget to set default value 43 | 44 | inline void operator += (node &other) { 45 | ... 46 | } 47 | }; -------------------------------------------------------------------------------- /data/segtree.cpp: -------------------------------------------------------------------------------- 1 | class segtree { 2 | public: 3 | struct node { 4 | // don't forget to set default value (used for leaves) 5 | // not necessarily neutral element! 6 | ... a = ...; 7 | 8 | void apply(int l, int r, ... v) { 9 | ... 10 | } 11 | }; 12 | 13 | node unite(const node &a, const node &b) const { 14 | node res; 15 | ... 16 | return res; 17 | } 18 | 19 | inline void push(int x, int l, int r) { 20 | int y = (l + r) >> 1; 21 | int z = x + ((y - l + 1) << 1); 22 | // push from x into (x + 1) and z 23 | ... 24 | /* 25 | if (tree[x].add != 0) { 26 | tree[x + 1].apply(l, y, tree[x].add); 27 | tree[z].apply(y + 1, r, tree[x].add); 28 | tree[x].add = 0; 29 | } 30 | */ 31 | } 32 | 33 | inline void pull(int x, int z) { 34 | tree[x] = unite(tree[x + 1], tree[z]); 35 | } 36 | 37 | int n; 38 | vector<node> tree; 39 | 40 | void build(int x, int l, int r) { 41 | if (l == r) { 42 | return; 43 | } 44 | int y = (l + r) >> 1; 45 | int z = x + ((y - l + 1) << 1); 46 | build(x + 1, l, y); 47 | build(z, y + 1, r); 48 | pull(x, z); 49 | } 50 | 51 | template <typename M> 52 | void build(int x, int l, int r, const vector<M> &v) { 53 | if (l == r) { 54 | tree[x].apply(l, r, v[l]); 55 | return; 56 | } 57 | int y = (l + r) >> 1; 58 | int z = x + ((y - l + 1) << 1); 59 | build(x + 1, l, y, v); 60 | build(z, y + 1, r, v); 61 | pull(x, z); 62 | } 63 | 64 | node get(int x, int l, int r, int ll, int rr) { 65 | if (ll <= l && r <= rr) { 66 | return tree[x]; 67 | } 68 | int y = (l + r) >> 1; 69 | int z = x + ((y - l + 1) << 1); 70 | push(x, l, r); 71 | node res{}; 72 | if (rr <= y) { 73 | res = get(x + 1, l, y, ll, rr); 74 | } else { 75 | if (ll > y) { 76 | res = get(z, y + 1, r, ll, rr); 77 | } else { 78 | res = unite(get(x + 1, l, y, ll, rr), get(z, y + 1, r, ll, rr)); 79 | } 80 | } 81 | pull(x, z); 82 | return res; 83 | } 84 | 85 | template <typename... M> 86 | void modify(int x, int l, int r, int ll, int rr, const M&... v) { 87 | if (ll <= l && r <= rr) { 88 | tree[x].apply(l, r, v...); 89 | return; 90 | } 91 | int y = (l + r) >> 1; 92 | int z = x + ((y - l + 1) << 1); 93 | push(x, l, r); 94 | if (ll <= y) { 95 | modify(x + 1, l, y, ll, rr, v...); 96 | } 97 | if (rr > y) { 98 | modify(z, y + 1, r, ll, rr, v...); 99 | } 100 | pull(x, z); 101 | } 102 | 103 | int find_first_knowingly(int x, int l, int r, const function<bool(const node&)> &f) { 104 | if (l == r) { 105 | return l; 106 | } 107 | push(x, l, r); 108 | int y = (l + r) >> 1; 109 | int z = x + ((y - l + 1) << 1); 110 | int res; 111 | if (f(tree[x + 1])) { 112 | res = find_first_knowingly(x + 1, l, y, f); 113 | } else { 114 | res = find_first_knowingly(z, y + 1, r, f); 115 | } 116 | pull(x, z); 117 | return res; 118 | } 119 | 120 | int find_first(int x, int l, int r, int ll, int rr, const function<bool(const node&)> &f) { 121 | if (ll <= l && r <= rr) { 122 | if (!f(tree[x])) { 123 | return -1; 124 | } 125 | return find_first_knowingly(x, l, r, f); 126 | } 127 | push(x, l, r); 128 | int y = (l + r) >> 1; 129 | int z = x + ((y - l + 1) << 1); 130 | int res = -1; 131 | if (ll <= y) { 132 | res = find_first(x + 1, l, y, ll, rr, f); 133 | } 134 | if (rr > y && res == -1) { 135 | res = find_first(z, y + 1, r, ll, rr, f); 136 | } 137 | pull(x, z); 138 | return res; 139 | } 140 | 141 | int find_last_knowingly(int x, int l, int r, const function<bool(const node&)> &f) { 142 | if (l == r) { 143 | return l; 144 | } 145 | push(x, l, r); 146 | int y = (l + r) >> 1; 147 | int z = x + ((y - l + 1) << 1); 148 | int res; 149 | if (f(tree[z])) { 150 | res = find_last_knowingly(z, y + 1, r, f); 151 | } else { 152 | res = find_last_knowingly(x + 1, l, y, f); 153 | } 154 | pull(x, z); 155 | return res; 156 | } 157 | 158 | int find_last(int x, int l, int r, int ll, int rr, const function<bool(const node&)> &f) { 159 | if (ll <= l && r <= rr) { 160 | if (!f(tree[x])) { 161 | return -1; 162 | } 163 | return find_last_knowingly(x, l, r, f); 164 | } 165 | push(x, l, r); 166 | int y = (l + r) >> 1; 167 | int z = x + ((y - l + 1) << 1); 168 | int res = -1; 169 | if (rr > y) { 170 | res = find_last(z, y + 1, r, ll, rr, f); 171 | } 172 | if (ll <= y && res == -1) { 173 | res = find_last(x + 1, l, y, ll, rr, f); 174 | } 175 | pull(x, z); 176 | return res; 177 | } 178 | 179 | segtree(int _n) : n(_n) { 180 | assert(n > 0); 181 | tree.resize(2 * n - 1); 182 | build(0, 0, n - 1); 183 | } 184 | 185 | template <typename M> 186 | segtree(const vector<M> &v) { 187 | n = v.size(); 188 | assert(n > 0); 189 | tree.resize(2 * n - 1); 190 | build(0, 0, n - 1, v); 191 | } 192 | 193 | node get(int ll, int rr) { 194 | assert(0 <= ll && ll <= rr && rr <= n - 1); 195 | return get(0, 0, n - 1, ll, rr); 196 | } 197 | 198 | node get(int p) { 199 | assert(0 <= p && p <= n - 1); 200 | return get(0, 0, n - 1, p, p); 201 | } 202 | 203 | template <typename... M> 204 | void modify(int ll, int rr, const M&... v) { 205 | assert(0 <= ll && ll <= rr && rr <= n - 1); 206 | modify(0, 0, n - 1, ll, rr, v...); 207 | } 208 | 209 | // find_first and find_last call all FALSE elements 210 | // to the left (right) of the sought position exactly once 211 | 212 | int find_first(int ll, int rr, const function<bool(const node&)> &f) { 213 | assert(0 <= ll && ll <= rr && rr <= n - 1); 214 | return find_first(0, 0, n - 1, ll, rr, f); 215 | } 216 | 217 | int find_last(int ll, int rr, const function<bool(const node&)> &f) { 218 | assert(0 <= ll && ll <= rr && rr <= n - 1); 219 | return find_last(0, 0, n - 1, ll, rr, f); 220 | } 221 | }; -------------------------------------------------------------------------------- /data/sparsetable.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nealwu/algo/9f69209c3af0ff268381f5b292f788418f910bdd/data/sparsetable.cpp -------------------------------------------------------------------------------- /flows/blossom.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> find_max_unweighted_matching(const undigraph<T>& g) { 3 | vector<int> mate(g.n, -1); 4 | vector<int> label(g.n); 5 | vector<int> parent(g.n); 6 | vector<int> orig(g.n); 7 | queue<int> q; 8 | vector<int> aux(g.n, -1); 9 | int aux_time = -1; 10 | auto lca = [&](int x, int y) { 11 | aux_time++; 12 | while (true) { 13 | if (x != -1) { 14 | if (aux[x] == aux_time) { 15 | return x; 16 | } 17 | aux[x] = aux_time; 18 | if (mate[x] == -1) { 19 | x = -1; 20 | } else { 21 | x = orig[parent[mate[x]]]; 22 | } 23 | } 24 | swap(x, y); 25 | } 26 | }; 27 | auto blossom = [&](int v, int w, int a) { 28 | while (orig[v] != a) { 29 | parent[v] = w; 30 | w = mate[v]; 31 | if (label[w] == 1) { 32 | label[w] = 0; 33 | q.push(w); 34 | } 35 | orig[v] = orig[w] = a; 36 | v = parent[w]; 37 | } 38 | }; 39 | auto augment = [&](int v) { 40 | while (v != -1) { 41 | int pv = parent[v]; 42 | int nv = mate[pv]; 43 | mate[v] = pv; 44 | mate[pv] = v; 45 | v = nv; 46 | } 47 | }; 48 | auto bfs = [&](int root) { 49 | fill(label.begin(), label.end(), -1); 50 | iota(orig.begin(), orig.end(), 0); 51 | while (!q.empty()) { 52 | q.pop(); 53 | } 54 | q.push(root); 55 | label[root] = 0; 56 | while (!q.empty()) { 57 | int v = q.front(); 58 | q.pop(); 59 | for (int id : g.g[v]) { 60 | auto &e = g.edges[id]; 61 | int x = e.from ^ e.to ^ v; 62 | if (label[x] == -1) { 63 | label[x] = 1; 64 | parent[x] = v; 65 | if (mate[x] == -1) { 66 | augment(x); 67 | return true; 68 | } 69 | label[mate[x]] = 0; 70 | q.push(mate[x]); 71 | continue; 72 | } 73 | if (label[x] == 0 && orig[v] != orig[x]) { 74 | int a = lca(orig[v], orig[x]); 75 | blossom(x, v, a); 76 | blossom(v, x, a); 77 | } 78 | } 79 | } 80 | return false; 81 | }; 82 | auto greedy = [&]() { 83 | vector<int> order(g.n); 84 | iota(order.begin(), order.end(), 0); 85 | shuffle(order.begin(), order.end(), mt19937(787788)); 86 | for (int i : order) { 87 | if (mate[i] == -1) { 88 | for (int id : g.g[i]) { 89 | auto &e = g.edges[id]; 90 | int to = e.from ^ e.to ^ i; 91 | if (mate[to] == -1) { 92 | mate[i] = to; 93 | mate[to] = i; 94 | break; 95 | } 96 | } 97 | } 98 | } 99 | }; 100 | greedy(); 101 | for (int i = 0; i < g.n; i++) { 102 | if (mate[i] == -1) { 103 | bfs(i); 104 | } 105 | } 106 | return mate; 107 | } -------------------------------------------------------------------------------- /flows/dinic-edge-ids.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class flow_graph { 3 | public: 4 | static constexpr T eps = (T) 1e-9; 5 | 6 | struct edge { 7 | int from; 8 | int to; 9 | T c; 10 | T f; 11 | }; 12 | 13 | vector< vector<int> > g; 14 | vector<edge> edges; 15 | int n; 16 | int st, fin; 17 | T flow; 18 | 19 | vector<int> ptr; 20 | vector<int> d; 21 | vector<int> q; 22 | 23 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 24 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 25 | g.resize(n); 26 | ptr.resize(n); 27 | d.resize(n); 28 | q.resize(n); 29 | flow = 0; 30 | } 31 | 32 | void clear_flow() { 33 | for (const edge &e : edges) { 34 | e.f = 0; 35 | } 36 | flow = 0; 37 | } 38 | 39 | void add(int from, int to, T forward_cap, T backward_cap) { 40 | assert(0 <= from && from < n && 0 <= to && to < n); 41 | g[from].push_back((int) edges.size()); 42 | edges.push_back({from, to, forward_cap, 0}); 43 | g[to].push_back((int) edges.size()); 44 | edges.push_back({to, from, backward_cap, 0}); 45 | } 46 | 47 | bool expath() { 48 | fill(d.begin(), d.end(), -1); 49 | q[0] = fin; 50 | d[fin] = 0; 51 | int beg = 0, end = 1; 52 | while (beg < end) { 53 | int i = q[beg++]; 54 | for (int id : g[i]) { 55 | const edge &e = edges[id]; 56 | const edge &back = edges[id ^ 1]; 57 | if (back.c - back.f > eps && d[e.to] == -1) { 58 | d[e.to] = d[i] + 1; 59 | if (e.to == st) { 60 | return true; 61 | } 62 | q[end++] = e.to; 63 | } 64 | } 65 | } 66 | return false; 67 | } 68 | 69 | T dfs(int v, T w) { 70 | if (v == fin) { 71 | return w; 72 | } 73 | int &j = ptr[v]; 74 | while (j >= 0) { 75 | int id = g[v][j]; 76 | const edge &e = edges[id]; 77 | if (e.c - e.f > eps && d[e.to] == d[v] - 1) { 78 | T t = dfs(e.to, min(e.c - e.f, w)); 79 | if (t > eps) { 80 | edges[id].f += t; 81 | edges[id ^ 1].f -= t; 82 | return t; 83 | } 84 | } 85 | j--; 86 | } 87 | return 0; 88 | } 89 | 90 | T max_flow() { 91 | while (expath()) { 92 | for (int i = 0; i < n; i++) { 93 | ptr[i] = (int) g[i].size() - 1; 94 | } 95 | T big_add = 0; 96 | while (true) { 97 | T add = dfs(st, numeric_limits<T>::max()); 98 | if (add <= eps) { 99 | break; 100 | } 101 | big_add += add; 102 | } 103 | if (big_add <= eps) { 104 | break; 105 | } 106 | flow += big_add; 107 | } 108 | return flow; 109 | } 110 | 111 | vector<bool> min_cut() { 112 | max_flow(); 113 | vector<bool> ret(n); 114 | for (int i = 0; i < n; i++) { 115 | ret[i] = (d[i] != -1); 116 | } 117 | return ret; 118 | } 119 | 120 | // Maximum flow / minimum cut, Dinic's algorithm 121 | // Usage: 122 | // 1) flow_graph<T> g(n, start, finish); [T == int / long long / double] 123 | // 2) g.add(from, to, forward_cap, backward_cap); 124 | // 3) cout << g.max_flow() << endl; 125 | // 4) vector<bool> cut = g.min_cut(); 126 | // for (auto &e : g.edges) 127 | // if (cut[e.from] != cut[e.to]) ; // edge e = (e.from -> e.to) is cut 128 | }; -------------------------------------------------------------------------------- /flows/dinic-old.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class flow_graph { 3 | public: 4 | static constexpr T eps = (T) 1e-9; 5 | 6 | struct edge { 7 | int to; 8 | T c; 9 | T f; 10 | int rev; 11 | }; 12 | 13 | vector< vector<edge> > g; 14 | vector<int> ptr; 15 | vector<int> d; 16 | vector<int> q; 17 | int n; 18 | int st, fin; 19 | T flow; 20 | 21 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 22 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 23 | g.resize(n); 24 | ptr.resize(n); 25 | d.resize(n); 26 | q.resize(n); 27 | flow = 0; 28 | } 29 | 30 | void clear_flow() { 31 | for (int i = 0; i < n; i++) { 32 | for (edge &e : g[i]) { 33 | e.f = 0; 34 | } 35 | } 36 | flow = 0; 37 | } 38 | 39 | void add(int from, int to, T forward_cap, T backward_cap) { 40 | assert(0 <= from && from < n && 0 <= to && to < n); 41 | int from_size = g[from].size(); 42 | int to_size = g[to].size(); 43 | g[from].push_back({to, forward_cap, 0, to_size}); 44 | g[to].push_back({from, backward_cap, 0, from_size}); 45 | } 46 | 47 | bool expath() { 48 | fill(d.begin(), d.end(), -1); 49 | q[0] = fin; 50 | d[fin] = 0; 51 | int beg = 0, end = 1; 52 | while (beg < end) { 53 | int i = q[beg++]; 54 | for (const edge &e : g[i]) { 55 | const edge &back = g[e.to][e.rev]; 56 | if (back.c - back.f > eps && d[e.to] == -1) { 57 | d[e.to] = d[i] + 1; 58 | if (e.to == st) { 59 | return true; 60 | } 61 | q[end++] = e.to; 62 | } 63 | } 64 | } 65 | return false; 66 | } 67 | 68 | T dfs(int v, T w) { 69 | if (v == fin) { 70 | return w; 71 | } 72 | int &j = ptr[v]; 73 | while (j >= 0) { 74 | const edge &e = g[v][j]; 75 | if (e.c - e.f > eps && d[e.to] == d[v] - 1) { 76 | T t = dfs(e.to, min(e.c - e.f, w)); 77 | if (t > eps) { 78 | g[v][j].f += t; 79 | g[e.to][e.rev].f -= t; 80 | return t; 81 | } 82 | } 83 | j--; 84 | } 85 | return 0; 86 | } 87 | 88 | T max_flow() { 89 | while (expath()) { 90 | for (int i = 0; i < n; i++) { 91 | ptr[i] = (int) g[i].size() - 1; 92 | } 93 | T big_add = 0; 94 | while (true) { 95 | T add = dfs(st, numeric_limits<T>::max()); 96 | if (add <= eps) { 97 | break; 98 | } 99 | big_add += add; 100 | } 101 | if (big_add <= eps) { 102 | break; 103 | } 104 | flow += big_add; 105 | } 106 | return flow; 107 | } 108 | 109 | vector<bool> min_cut() { 110 | max_flow(); 111 | vector<bool> ret(n); 112 | for (int i = 0; i < n; i++) { 113 | ret[i] = (d[i] != -1); 114 | } 115 | return ret; 116 | } 117 | }; -------------------------------------------------------------------------------- /flows/dinic.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class dinic { 3 | public: 4 | flow_graph<T> &g; 5 | 6 | vector<int> ptr; 7 | vector<int> d; 8 | vector<int> q; 9 | 10 | dinic(flow_graph<T> &_g) : g(_g) { 11 | ptr.resize(g.n); 12 | d.resize(g.n); 13 | q.resize(g.n); 14 | } 15 | 16 | bool expath() { 17 | fill(d.begin(), d.end(), -1); 18 | q[0] = g.fin; 19 | d[g.fin] = 0; 20 | int beg = 0, end = 1; 21 | while (beg < end) { 22 | int i = q[beg++]; 23 | for (int id : g.g[i]) { 24 | const auto &e = g.edges[id]; 25 | const auto &back = g.edges[id ^ 1]; 26 | if (back.c - back.f > g.eps && d[e.to] == -1) { 27 | d[e.to] = d[i] + 1; 28 | if (e.to == g.st) { 29 | return true; 30 | } 31 | q[end++] = e.to; 32 | } 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | T dfs(int v, T w) { 39 | if (v == g.fin) { 40 | return w; 41 | } 42 | int &j = ptr[v]; 43 | while (j >= 0) { 44 | int id = g.g[v][j]; 45 | const auto &e = g.edges[id]; 46 | if (e.c - e.f > g.eps && d[e.to] == d[v] - 1) { 47 | T t = dfs(e.to, min(e.c - e.f, w)); 48 | if (t > g.eps) { 49 | g.edges[id].f += t; 50 | g.edges[id ^ 1].f -= t; 51 | return t; 52 | } 53 | } 54 | j--; 55 | } 56 | return 0; 57 | } 58 | 59 | T max_flow() { 60 | while (expath()) { 61 | for (int i = 0; i < g.n; i++) { 62 | ptr[i] = (int) g.g[i].size() - 1; 63 | } 64 | T big_add = 0; 65 | while (true) { 66 | T add = dfs(g.st, numeric_limits<T>::max()); 67 | if (add <= g.eps) { 68 | break; 69 | } 70 | big_add += add; 71 | } 72 | if (big_add <= g.eps) { 73 | break; 74 | } 75 | g.flow += big_add; 76 | } 77 | return g.flow; 78 | } 79 | 80 | vector<bool> min_cut() { 81 | max_flow(); 82 | vector<bool> ret(g.n); 83 | for (int i = 0; i < g.n; i++) { 84 | ret[i] = (d[i] != -1); 85 | } 86 | return ret; 87 | } 88 | }; -------------------------------------------------------------------------------- /flows/fastflow-other.cpp: -------------------------------------------------------------------------------- 1 | // https://pastebin.com/exQM152L 2 | 3 | // Doesn't walk through the whole path during augment at the cost of bigger constant 4 | // Not recommended to use with double 5 | 6 | template <typename T> 7 | class flow_graph { 8 | public: 9 | static constexpr T eps = (T) 1e-9; 10 | 11 | struct edge { 12 | int to; 13 | T c; 14 | T f; 15 | int rev; 16 | }; 17 | 18 | vector< vector<edge> > g; 19 | vector<int> ptr; 20 | vector<int> d; 21 | vector<int> q; 22 | vector<int> cnt_on_layer; 23 | vector<int> prev_edge; 24 | vector<T> to_push; 25 | vector<T> pushed; 26 | vector<int> smallest; 27 | bool can_reach_sink; 28 | 29 | int n; 30 | int st, fin; 31 | T flow; 32 | 33 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 34 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 35 | g.resize(n); 36 | ptr.resize(n); 37 | d.resize(n); 38 | q.resize(n); 39 | cnt_on_layer.resize(n + 1); 40 | prev_edge.resize(n); 41 | to_push.resize(n); 42 | pushed.resize(n); 43 | smallest.resize(n); 44 | flow = 0; 45 | } 46 | 47 | void clear_flow() { 48 | for (int i = 0; i < n; i++) { 49 | for (edge &e : g[i]) { 50 | e.f = 0; 51 | } 52 | } 53 | flow = 0; 54 | } 55 | 56 | void add(int from, int to, T forward_cap, T backward_cap) { 57 | assert(0 <= from && from < n && 0 <= to && to < n); 58 | int from_size = g[from].size(); 59 | int to_size = g[to].size(); 60 | g[from].push_back({to, forward_cap, 0, to_size}); 61 | g[to].push_back({from, backward_cap, 0, from_size}); 62 | } 63 | 64 | bool expath() { 65 | fill(d.begin(), d.end(), n); 66 | q[0] = fin; 67 | d[fin] = 0; 68 | fill(cnt_on_layer.begin(), cnt_on_layer.end(), 0); 69 | cnt_on_layer[n] = n - 1; 70 | cnt_on_layer[0] = 1; 71 | int beg = 0, end = 1; 72 | while (beg < end) { 73 | int i = q[beg++]; 74 | for (const edge &e : g[i]) { 75 | const edge &back = g[e.to][e.rev]; 76 | if (back.c - back.f > eps && d[e.to] == n) { 77 | cnt_on_layer[d[e.to]]--; 78 | d[e.to] = d[i] + 1; 79 | cnt_on_layer[d[e.to]]++; 80 | q[end++] = e.to; 81 | } 82 | } 83 | } 84 | return (d[st] != n); 85 | } 86 | 87 | void rollback(int &v) { 88 | edge &e = g[v][prev_edge[v]]; 89 | if (pushed[v]) { 90 | edge &back = g[e.to][e.rev]; 91 | back.f += pushed[v]; 92 | e.f -= pushed[v]; 93 | pushed[e.to] += pushed[v]; 94 | to_push[e.to] -= pushed[v]; 95 | pushed[v] = 0; 96 | } 97 | v = e.to; 98 | } 99 | 100 | void augment(int &v) { 101 | pushed[v] += to_push[v]; 102 | to_push[v] = 0; 103 | int new_v = smallest[v]; 104 | while (v != new_v) { 105 | rollback(v); 106 | } 107 | } 108 | 109 | void retreat(int &v) { 110 | int new_dist = n - 1; 111 | for (const edge &e : g[v]) { 112 | if (e.c - e.f > eps && d[e.to] < new_dist) { 113 | new_dist = d[e.to]; 114 | } 115 | } 116 | cnt_on_layer[d[v]]--; 117 | if (cnt_on_layer[d[v]] == 0) { 118 | if (new_dist + 1 > d[v]) { 119 | can_reach_sink = false; 120 | } 121 | } 122 | d[v] = new_dist + 1; 123 | cnt_on_layer[d[v]]++; 124 | if (v != st) { 125 | rollback(v); 126 | } 127 | } 128 | 129 | T max_flow() { 130 | can_reach_sink = true; 131 | for (int i = 0; i < n; i++) { 132 | ptr[i] = (int) g[i].size() - 1; 133 | } 134 | if (expath()) { 135 | int v = st; 136 | to_push[v] = numeric_limits<T>::max(); 137 | smallest[v] = v; 138 | while (d[st] < n) { 139 | while (ptr[v] >= 0) { 140 | const edge &e = g[v][ptr[v]]; 141 | if (e.c - e.f > eps && d[e.to] == d[v] - 1) { 142 | prev_edge[e.to] = e.rev; 143 | to_push[e.to] = to_push[v]; 144 | smallest[e.to] = smallest[v]; 145 | if (e.c - e.f < to_push[e.to]) { 146 | to_push[e.to] = e.c - e.f; 147 | smallest[e.to] = v; 148 | } 149 | v = e.to; 150 | if (v == fin) { 151 | augment(v); 152 | } 153 | break; 154 | } 155 | ptr[v]--; 156 | } 157 | if (ptr[v] < 0) { 158 | ptr[v] = (int) g[v].size() - 1; 159 | retreat(v); 160 | if (!can_reach_sink) { 161 | break; 162 | } 163 | } 164 | } 165 | while (v != st) { 166 | rollback(v); 167 | } 168 | flow += pushed[st]; 169 | pushed[st] = 0; 170 | } 171 | return flow; 172 | } 173 | 174 | vector<bool> min_cut() { 175 | max_flow(); 176 | assert(!expath()); 177 | vector<bool> ret(n); 178 | for (int i = 0; i < n; i++) { 179 | ret[i] = (d[i] != n); 180 | } 181 | return ret; 182 | } 183 | }; -------------------------------------------------------------------------------- /flows/fastflow.cpp: -------------------------------------------------------------------------------- 1 | // https://pastebin.com/exQM152L 2 | 3 | template <typename T> 4 | class flow_graph { 5 | public: 6 | static constexpr T eps = (T) 1e-9; 7 | 8 | struct edge { 9 | int to; 10 | T c; 11 | T f; 12 | int rev; 13 | }; 14 | 15 | vector< vector<edge> > g; 16 | vector<int> ptr; 17 | vector<int> d; 18 | vector<int> q; 19 | vector<int> cnt_on_layer; 20 | vector<int> prev_edge; 21 | bool can_reach_sink; 22 | 23 | int n; 24 | int st, fin; 25 | T flow; 26 | 27 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 28 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 29 | g.resize(n); 30 | ptr.resize(n); 31 | d.resize(n); 32 | q.resize(n); 33 | cnt_on_layer.resize(n + 1); 34 | prev_edge.resize(n); 35 | flow = 0; 36 | } 37 | 38 | void clear_flow() { 39 | for (int i = 0; i < n; i++) { 40 | for (edge &e : g[i]) { 41 | e.f = 0; 42 | } 43 | } 44 | flow = 0; 45 | } 46 | 47 | void add(int from, int to, T forward_cap, T backward_cap) { 48 | assert(0 <= from && from < n && 0 <= to && to < n); 49 | int from_size = g[from].size(); 50 | int to_size = g[to].size(); 51 | g[from].push_back({to, forward_cap, 0, to_size}); 52 | g[to].push_back({from, backward_cap, 0, from_size}); 53 | } 54 | 55 | bool expath() { 56 | fill(d.begin(), d.end(), n); 57 | q[0] = fin; 58 | d[fin] = 0; 59 | fill(cnt_on_layer.begin(), cnt_on_layer.end(), 0); 60 | cnt_on_layer[n] = n - 1; 61 | cnt_on_layer[0] = 1; 62 | int beg = 0, end = 1; 63 | while (beg < end) { 64 | int i = q[beg++]; 65 | for (const edge &e : g[i]) { 66 | const edge &back = g[e.to][e.rev]; 67 | if (back.c - back.f > eps && d[e.to] == n) { 68 | cnt_on_layer[d[e.to]]--; 69 | d[e.to] = d[i] + 1; 70 | cnt_on_layer[d[e.to]]++; 71 | q[end++] = e.to; 72 | } 73 | } 74 | } 75 | return (d[st] != n); 76 | } 77 | 78 | T augment(int &v) { 79 | T cur = numeric_limits<T>::max(); 80 | int i = fin; 81 | while (i != st) { 82 | const edge &e = g[i][prev_edge[i]]; 83 | const edge &back = g[e.to][e.rev]; 84 | cur = min(cur, back.c - back.f); 85 | i = e.to; 86 | } 87 | i = fin; 88 | while (i != st) { 89 | edge &e = g[i][prev_edge[i]]; 90 | edge &back = g[e.to][e.rev]; 91 | back.f += cur; 92 | e.f -= cur; 93 | i = e.to; 94 | if (back.c - back.f <= eps) { 95 | v = i; 96 | } 97 | } 98 | return cur; 99 | } 100 | 101 | int retreat(int v) { 102 | int new_dist = n - 1; 103 | for (const edge &e : g[v]) { 104 | if (e.c - e.f > eps && d[e.to] < new_dist) { 105 | new_dist = d[e.to]; 106 | } 107 | } 108 | cnt_on_layer[d[v]]--; 109 | if (cnt_on_layer[d[v]] == 0) { 110 | if (new_dist + 1 > d[v]) { 111 | can_reach_sink = false; 112 | } 113 | } 114 | d[v] = new_dist + 1; 115 | cnt_on_layer[d[v]]++; 116 | if (v != st) { 117 | v = g[v][prev_edge[v]].to; 118 | } 119 | return v; 120 | } 121 | 122 | T max_flow() { 123 | can_reach_sink = true; 124 | for (int i = 0; i < n; i++) { 125 | ptr[i] = (int) g[i].size() - 1; 126 | } 127 | if (expath()) { 128 | int v = st; 129 | while (d[st] < n) { 130 | while (ptr[v] >= 0) { 131 | const edge &e = g[v][ptr[v]]; 132 | if (e.c - e.f > eps && d[e.to] == d[v] - 1) { 133 | prev_edge[e.to] = e.rev; 134 | v = e.to; 135 | if (v == fin) { 136 | flow += augment(v); 137 | } 138 | break; 139 | } 140 | ptr[v]--; 141 | } 142 | if (ptr[v] < 0) { 143 | ptr[v] = (int) g[v].size() - 1; 144 | v = retreat(v); 145 | if (!can_reach_sink) { 146 | break; 147 | } 148 | } 149 | } 150 | } 151 | return flow; 152 | } 153 | 154 | vector<bool> min_cut() { 155 | max_flow(); 156 | assert(!expath()); 157 | vector<bool> ret(n); 158 | for (int i = 0; i < n; i++) { 159 | ret[i] = (d[i] != n); 160 | } 161 | return ret; 162 | } 163 | }; -------------------------------------------------------------------------------- /flows/flow_decomposition.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class flow_decomposition { 3 | public: 4 | const flow_graph<T> &g; 5 | 6 | vector< vector<int> > paths; 7 | vector<T> path_flows; 8 | vector< vector<int> > cycles; 9 | vector<T> cycle_flows; 10 | 11 | flow_decomposition(const flow_graph<T> &_g) : g(_g) { 12 | } 13 | 14 | void decompose() { 15 | vector<T> fs(g.edges.size()); 16 | for (int i = 0; i < (int) g.edges.size(); i++) { 17 | fs[i] = g.edges[i].f; 18 | } 19 | paths.clear(); 20 | path_flows.clear(); 21 | cycles.clear(); 22 | cycle_flows.clear(); 23 | vector<int> ptr(g.n); 24 | for (int i = 0; i < g.n; i++) { 25 | ptr[i] = (int) g.g[i].size() - 1; 26 | } 27 | vector<int> was(g.n, -1); 28 | int start = g.st; 29 | for (int iter = 0; ; iter++) { 30 | bool found_start = false; 31 | while (true) { 32 | if (ptr[start] >= 0) { 33 | int id = g.g[start][ptr[start]]; 34 | if (fs[id] > g.eps) { 35 | found_start = true; 36 | break; 37 | } 38 | ptr[start]--; 39 | continue; 40 | } 41 | start = (start + 1) % g.n; 42 | if (start == g.st) { 43 | break; 44 | } 45 | } 46 | if (!found_start) { 47 | break; 48 | } 49 | vector<int> path; 50 | bool is_cycle = false; 51 | int v = start; 52 | while (true) { 53 | if (v == g.fin) { 54 | break; 55 | } 56 | if (was[v] == iter) { 57 | bool found = false; 58 | for (int i = 0; i < (int) path.size(); i++) { 59 | int id = path[i]; 60 | auto &e = g.edges[id]; 61 | if (e.from == v) { 62 | path.erase(path.begin(), path.begin() + i); 63 | found = true; 64 | break; 65 | } 66 | } 67 | assert(found); 68 | is_cycle = true; 69 | break; 70 | } 71 | was[v] = iter; 72 | bool found = false; 73 | while (ptr[v] >= 0) { 74 | int id = g.g[v][ptr[v]]; 75 | if (fs[id] > g.eps) { 76 | path.push_back(id); 77 | v = g.edges[id].to; 78 | found = true; 79 | break; 80 | } 81 | ptr[v]--; 82 | } 83 | assert(found); 84 | } 85 | T path_flow = numeric_limits<T>::max(); 86 | for (int id : path) { 87 | path_flow = min(path_flow, fs[id]); 88 | } 89 | for (int id : path) { 90 | fs[id] -= path_flow; 91 | fs[id ^ 1] += path_flow; 92 | } 93 | if (is_cycle) { 94 | cycles.push_back(path); 95 | cycle_flows.push_back(path_flow); 96 | } else { 97 | paths.push_back(path); 98 | path_flows.push_back(path_flow); 99 | } 100 | } 101 | for (const T& f : fs) { 102 | assert(-g.eps <= f && f <= g.eps); 103 | } 104 | } 105 | }; -------------------------------------------------------------------------------- /flows/flow_graph.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class flow_graph { 3 | public: 4 | static constexpr T eps = (T) 1e-9; 5 | 6 | struct edge { 7 | int from; 8 | int to; 9 | T c; 10 | T f; 11 | }; 12 | 13 | vector< vector<int> > g; 14 | vector<edge> edges; 15 | int n; 16 | int st; 17 | int fin; 18 | T flow; 19 | 20 | flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 21 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 22 | g.resize(n); 23 | flow = 0; 24 | } 25 | 26 | void clear_flow() { 27 | for (const edge &e : edges) { 28 | e.f = 0; 29 | } 30 | flow = 0; 31 | } 32 | 33 | int add(int from, int to, T forward_cap, T backward_cap) { 34 | assert(0 <= from && from < n && 0 <= to && to < n); 35 | int id = (int) edges.size(); 36 | g[from].push_back(id); 37 | edges.push_back({from, to, forward_cap, 0}); 38 | g[to].push_back(id + 1); 39 | edges.push_back({to, from, backward_cap, 0}); 40 | return id; 41 | } 42 | }; -------------------------------------------------------------------------------- /flows/gomory_hu-old.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | forest<T> gomory_hu(const undigraph<T> &g) { 3 | int n = g.n; 4 | if (n == 1) { 5 | return forest<T>(n); 6 | } 7 | flow_graph<T> fg(n, 0, 1); 8 | for (auto &e : g.edges) { 9 | fg.add(e.from, e.to, e.cost, e.cost); 10 | } 11 | vector< vector<int> > dist(n, vector<int>(n, numeric_limits<T>::max())); 12 | function<void(vector<int>)> dfs = [&g, &n, &fg, &dist, &dfs](vector<int> group) { 13 | int sz = group.size(); 14 | if (sz == 1) { 15 | return; 16 | } 17 | fg.clear_flow(); 18 | fg.st = group[0]; 19 | fg.fin = group[1]; 20 | T flow = fg.max_flow(); 21 | vector<bool> cut = fg.min_cut(); 22 | for (int i = 0; i < n; i++) { 23 | for (int j = i + 1; j < n; j++) { 24 | if (cut[i] != cut[j]) { 25 | dist[i][j] = min(dist[i][j], flow); 26 | } 27 | } 28 | } 29 | vector<int> new_groups[2]; 30 | for (int v : group) { 31 | new_groups[(int) cut[v]].push_back(v); 32 | } 33 | for (int id = 0; id < 2; id++) { 34 | dfs(new_groups[id]); 35 | } 36 | }; 37 | vector<int> group(n); 38 | iota(group.begin(), group.end(), 0); 39 | dfs(group); 40 | undigraph<T> mg(n); 41 | for (int i = 0; i < n; i++) { 42 | for (int j = i + 1; j < n; j++) { 43 | mg.add(i, j, -dist[i][j]); 44 | } 45 | } 46 | T foo; 47 | vector<int> ids = mst(mg, foo); 48 | forest<T> ret(n); 49 | for (int id : ids) { 50 | auto &e = mg.edges[id]; 51 | ret.add(e.from, e.to, -e.cost); 52 | } 53 | return ret; 54 | // don't be lazy next time! 55 | // implement a proper gomory-hu tree 56 | } -------------------------------------------------------------------------------- /flows/gomory_hu.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | forest<T> gomory_hu(const undigraph<T> &g) { 3 | int n = g.n; 4 | flow_graph<T> fg(n, 0, 1); 5 | for (auto &e : g.edges) { 6 | fg.add(e.from, e.to, e.cost, e.cost); 7 | } 8 | forest<T> ret(n); 9 | vector<int> pr(n, 0); 10 | for (int i = 1; i < n; i++) { 11 | fg.clear_flow(); 12 | fg.st = i; 13 | fg.fin = pr[i]; 14 | T flow = fg.max_flow(); 15 | vector<bool> cut = fg.min_cut(); 16 | for (int j = i + 1; j < n; j++) { 17 | if (cut[j] == cut[i] && pr[j] == pr[i]) { 18 | pr[j] = i; 19 | } 20 | } 21 | ret.add(i, pr[i], flow); 22 | } 23 | return ret; 24 | // can be optimized by compressing components 25 | } -------------------------------------------------------------------------------- /flows/hungarian-arrays.cpp: -------------------------------------------------------------------------------- 1 | template<typename T> 2 | class hungarian { 3 | public: 4 | static const int MAX_N = ... + 1; 5 | 6 | int n; 7 | int m; 8 | T a[MAX_N][MAX_N]; 9 | T u[MAX_N]; 10 | T v[MAX_N]; 11 | int pa[MAX_N]; 12 | int pb[MAX_N]; 13 | int way[MAX_N]; 14 | T minv[MAX_N]; 15 | bool used[MAX_N]; 16 | T inf; 17 | 18 | hungarian(int _n, int _m) : n(_n), m(_m) { 19 | assert(n <= m); 20 | T zero = T{}; 21 | fill(u, u + n + 1, zero); 22 | fill(v, v + m + 1, zero); 23 | fill(pa, pa + n + 1, -1); 24 | fill(pb, pb + m + 1, -1); 25 | inf = numeric_limits<T>::max(); 26 | } 27 | 28 | inline void add_row(int i) { 29 | fill(minv, minv + m + 1, inf); 30 | fill(used, used + m + 1, false); 31 | pb[m] = i; 32 | pa[i] = m; 33 | int j0 = m; 34 | do { 35 | used[j0] = true; 36 | int i0 = pb[j0]; 37 | T delta = inf; 38 | int j1 = -1; 39 | for (int j = 0; j < m; j++) { 40 | if (!used[j]) { 41 | T cur = a[i0][j] - u[i0] - v[j]; 42 | if (cur < minv[j]) { 43 | minv[j] = cur; 44 | way[j] = j0; 45 | } 46 | if (minv[j] < delta) { 47 | delta = minv[j]; 48 | j1 = j; 49 | } 50 | } 51 | } 52 | for (int j = 0; j <= m; j++) { 53 | if (used[j]) { 54 | u[pb[j]] += delta; 55 | v[j] -= delta; 56 | } else { 57 | minv[j] -= delta; 58 | } 59 | } 60 | j0 = j1; 61 | } while (pb[j0] != -1); 62 | do { 63 | int j1 = way[j0]; 64 | pb[j0] = pb[j1]; 65 | pa[pb[j0]] = j0; 66 | j0 = j1; 67 | } while (j0 != m); 68 | } 69 | 70 | inline T current_score() { 71 | return -v[m]; 72 | } 73 | 74 | inline T solve() { 75 | for (int i = 0; i < n; i++) { 76 | add_row(i); 77 | } 78 | return current_score(); 79 | } 80 | }; -------------------------------------------------------------------------------- /flows/hungarian.cpp: -------------------------------------------------------------------------------- 1 | template<typename T> 2 | class hungarian { 3 | public: 4 | int n; 5 | int m; 6 | vector< vector<T> > a; 7 | vector<T> u; 8 | vector<T> v; 9 | vector<int> pa; 10 | vector<int> pb; 11 | vector<int> way; 12 | vector<T> minv; 13 | vector<bool> used; 14 | T inf; 15 | 16 | hungarian(int _n, int _m) : n(_n), m(_m) { 17 | assert(n <= m); 18 | a = vector< vector<T> >(n, vector<T>(m)); 19 | u = vector<T>(n + 1); 20 | v = vector<T>(m + 1); 21 | pa = vector<int>(n + 1, -1); 22 | pb = vector<int>(m + 1, -1); 23 | way = vector<int>(m, -1); 24 | minv = vector<T>(m); 25 | used = vector<bool>(m + 1); 26 | inf = numeric_limits<T>::max(); 27 | } 28 | 29 | inline void add_row(int i) { 30 | fill(minv.begin(), minv.end(), inf); 31 | fill(used.begin(), used.end(), false); 32 | pb[m] = i; 33 | pa[i] = m; 34 | int j0 = m; 35 | do { 36 | used[j0] = true; 37 | int i0 = pb[j0]; 38 | T delta = inf; 39 | int j1 = -1; 40 | for (int j = 0; j < m; j++) { 41 | if (!used[j]) { 42 | T cur = a[i0][j] - u[i0] - v[j]; 43 | if (cur < minv[j]) { 44 | minv[j] = cur; 45 | way[j] = j0; 46 | } 47 | if (minv[j] < delta) { 48 | delta = minv[j]; 49 | j1 = j; 50 | } 51 | } 52 | } 53 | for (int j = 0; j <= m; j++) { 54 | if (used[j]) { 55 | u[pb[j]] += delta; 56 | v[j] -= delta; 57 | } else { 58 | minv[j] -= delta; 59 | } 60 | } 61 | j0 = j1; 62 | } while (pb[j0] != -1); 63 | do { 64 | int j1 = way[j0]; 65 | pb[j0] = pb[j1]; 66 | pa[pb[j0]] = j0; 67 | j0 = j1; 68 | } while (j0 != m); 69 | } 70 | 71 | inline T current_score() { 72 | return -v[m]; 73 | } 74 | 75 | inline T solve() { 76 | for (int i = 0; i < n; i++) { 77 | add_row(i); 78 | } 79 | return current_score(); 80 | } 81 | }; -------------------------------------------------------------------------------- /flows/matching.cpp: -------------------------------------------------------------------------------- 1 | class matching { 2 | public: 3 | vector< vector<int> > g; 4 | vector<int> pa; 5 | vector<int> pb; 6 | vector<int> was; 7 | int n, m; 8 | int res; 9 | int iter; 10 | 11 | matching(int _n, int _m) : n(_n), m(_m) { 12 | assert(0 <= n && 0 <= m); 13 | pa = vector<int>(n, -1); 14 | pb = vector<int>(m, -1); 15 | was = vector<int>(n, 0); 16 | g.resize(n); 17 | res = 0; 18 | iter = 0; 19 | } 20 | 21 | void add(int from, int to) { 22 | assert(0 <= from && from < n && 0 <= to && to < m); 23 | g[from].push_back(to); 24 | } 25 | 26 | bool dfs(int v) { 27 | was[v] = iter; 28 | for (int u : g[v]) { 29 | if (pb[u] == -1) { 30 | pa[v] = u; 31 | pb[u] = v; 32 | return true; 33 | } 34 | } 35 | for (int u : g[v]) { 36 | if (was[pb[u]] != iter && dfs(pb[u])) { 37 | pa[v] = u; 38 | pb[u] = v; 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | int solve() { 46 | while (true) { 47 | iter++; 48 | int add = 0; 49 | for (int i = 0; i < n; i++) { 50 | if (pa[i] == -1 && dfs(i)) { 51 | add++; 52 | } 53 | } 54 | if (add == 0) { 55 | break; 56 | } 57 | res += add; 58 | } 59 | return res; 60 | } 61 | 62 | int run_one(int v) { 63 | if (pa[v] != -1) { 64 | return 0; 65 | } 66 | iter++; 67 | return (int) dfs(v); 68 | } 69 | }; -------------------------------------------------------------------------------- /flows/mcmf.cpp: -------------------------------------------------------------------------------- 1 | template <typename T, typename C> 2 | class mcmf { 3 | public: 4 | static constexpr T eps = (T) 1e-9; 5 | 6 | struct edge { 7 | int from; 8 | int to; 9 | T c; 10 | T f; 11 | C cost; 12 | }; 13 | 14 | vector< vector<int> > g; 15 | vector<edge> edges; 16 | vector<C> d; 17 | vector<int> q; 18 | vector<bool> in_queue; 19 | vector<int> pe; 20 | int n; 21 | int st, fin; 22 | T flow; 23 | C cost; 24 | 25 | mcmf(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) { 26 | assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin); 27 | g.resize(n); 28 | d.resize(n); 29 | in_queue.resize(n); 30 | pe.resize(n); 31 | flow = 0; 32 | cost = 0; 33 | } 34 | 35 | void clear_flow() { 36 | for (const edge &e : edges) { 37 | e.f = 0; 38 | } 39 | flow = 0; 40 | } 41 | 42 | void add(int from, int to, T forward_cap, T backward_cap, C cost) { 43 | assert(0 <= from && from < n && 0 <= to && to < n); 44 | g[from].push_back((int) edges.size()); 45 | edges.push_back({from, to, forward_cap, 0, cost}); 46 | g[to].push_back((int) edges.size()); 47 | edges.push_back({to, from, backward_cap, 0, -cost}); 48 | } 49 | 50 | bool expath() { 51 | fill(d.begin(), d.end(), numeric_limits<C>::max()); 52 | q.clear(); 53 | q.push_back(st); 54 | d[st] = 0; 55 | in_queue[st] = true; 56 | int beg = 0; 57 | bool found = false; 58 | while (beg < (int) q.size()) { 59 | int i = q[beg++]; 60 | if (i == fin) { 61 | found = true; 62 | } 63 | in_queue[i] = false; 64 | for (int id : g[i]) { 65 | const edge &e = edges[id]; 66 | if (e.c - e.f > eps && d[i] + e.cost < d[e.to]) { 67 | d[e.to] = d[i] + e.cost; 68 | pe[e.to] = id; 69 | if (!in_queue[e.to]) { 70 | q.push_back(e.to); 71 | in_queue[e.to] = true; 72 | } 73 | } 74 | } 75 | } 76 | if (found) { 77 | T push = numeric_limits<T>::max(); 78 | int v = fin; 79 | while (v != st) { 80 | const edge &e = edges[pe[v]]; 81 | push = min(push, e.c - e.f); 82 | v = e.from; 83 | } 84 | v = fin; 85 | while (v != st) { 86 | edge &e = edges[pe[v]]; 87 | e.f += push; 88 | edge &back = edges[pe[v] ^ 1]; 89 | back.f -= push; 90 | v = e.from; 91 | } 92 | flow += push; 93 | cost += push * d[fin]; 94 | } 95 | return found; 96 | } 97 | 98 | pair<T, C> max_flow_min_cost() { 99 | while (expath()) { 100 | } 101 | return make_pair(flow, cost); 102 | } 103 | }; -------------------------------------------------------------------------------- /graph/bicone.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> find_bicone(dfs_undigraph<T> &g, int &cnt) { 3 | g.dfs_all(); 4 | vector<int> vertex_comp(g.n); 5 | cnt = 0; 6 | for (int i : g.order) { 7 | if (g.pv[i] == -1 || g.min_depth[i] == g.depth[i]) { 8 | vertex_comp[i] = cnt++; 9 | } else { 10 | vertex_comp[i] = vertex_comp[g.pv[i]]; 11 | } 12 | } 13 | return vertex_comp; 14 | } -------------------------------------------------------------------------------- /graph/biconv.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> find_biconv(dfs_undigraph<T> &g, int &cnt) { 3 | g.dfs_all(); 4 | vector<int> vertex_comp(g.n); 5 | cnt = 0; 6 | for (int i : g.order) { 7 | if (g.pv[i] == -1) { 8 | vertex_comp[i] = -1; 9 | continue; 10 | } 11 | if (g.min_depth[i] >= g.depth[g.pv[i]]) { 12 | vertex_comp[i] = cnt++; 13 | } else { 14 | vertex_comp[i] = vertex_comp[g.pv[i]]; 15 | } 16 | } 17 | vector<int> edge_comp(g.edges.size(), -1); 18 | for (int id = 0; id < (int) g.edges.size(); id++) { 19 | if (g.ignore != nullptr && g.ignore(id)) { 20 | continue; 21 | } 22 | int x = g.edges[id].from; 23 | int y = g.edges[id].to; 24 | int z = (g.depth[x] > g.depth[y] ? x : y); 25 | edge_comp[id] = vertex_comp[z]; 26 | } 27 | return edge_comp; 28 | } -------------------------------------------------------------------------------- /graph/bridges.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<bool> find_bridges(dfs_undigraph<T> &g) { 3 | g.dfs_all(); 4 | vector<bool> bridge(g.edges.size(), false); 5 | for (int i = 0; i < g.n; i++) { 6 | if (g.pv[i] != -1 && g.min_depth[i] == g.depth[i]) { 7 | bridge[g.pe[i]] = true; 8 | } 9 | } 10 | return bridge; 11 | } -------------------------------------------------------------------------------- /graph/cutpoints.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<bool> find_cutpoints(dfs_undigraph<T> &g) { 3 | g.dfs_all(); 4 | vector<bool> cutpoint(g.n, false); 5 | for (int i = 0; i < g.n; i++) { 6 | if (g.pv[i] != -1 && g.min_depth[i] >= g.depth[g.pv[i]]) { 7 | cutpoint[g.pv[i]] = true; 8 | } 9 | } 10 | vector<int> children(g.n, 0); 11 | for (int i = 0; i < g.n; i++) { 12 | if (g.pv[i] != -1) { 13 | children[g.pv[i]]++; 14 | } 15 | } 16 | for (int i = 0; i < g.n; i++) { 17 | if (g.pv[i] == -1 && children[i] < 2) { 18 | cutpoint[i] = false; 19 | } 20 | } 21 | return cutpoint; 22 | } -------------------------------------------------------------------------------- /graph/cycles.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector< vector<int> > find_cycles(const graph<T> &g, int bound_cnt = 1 << 30, int bound_size = 1 << 30) { 3 | vector<int> was(g.n, -1); 4 | vector<int> st; 5 | vector< vector<int> > cycles; 6 | int total_size = 0; 7 | function<void(int, int)> dfs = [&](int v, int pe) { 8 | if ((int) cycles.size() >= bound_cnt || total_size >= bound_size) { 9 | return; 10 | } 11 | was[v] = (int) st.size(); 12 | for (int id : g.g[v]) { 13 | if (id == pe || (g.ignore != nullptr && g.ignore(id))) { 14 | continue; 15 | } 16 | auto &e = g.edges[id]; 17 | int to = e.from ^ e.to ^ v; 18 | if (was[to] >= 0) { 19 | vector<int> cycle(1, id); 20 | for (int j = was[to]; j < (int) st.size(); j++) { 21 | cycle.push_back(st[j]); 22 | } 23 | cycles.push_back(cycle); 24 | total_size += (int) cycle.size(); 25 | if ((int) cycles.size() >= bound_cnt || total_size >= bound_size) { 26 | return; 27 | } 28 | continue; 29 | } 30 | if (was[to] == -1) { 31 | st.push_back(id); 32 | dfs(to, id); 33 | st.pop_back(); 34 | } 35 | } 36 | was[v] = -2; 37 | }; 38 | for (int i = 0; i < g.n; i++) { 39 | if (was[i] == -1) { 40 | dfs(i, -1); 41 | } 42 | } 43 | return cycles; 44 | // cycles are given by edge ids, all cycles are simple 45 | // breaks after getting bound_cnt cycles or total_size >= bound_size 46 | // digraph: finds at least one cycle in every connected component (if not broken) 47 | // undigraph: finds cycle basis 48 | } 49 | 50 | template <typename T> 51 | vector<int> edges_to_vertices(const graph<T> &g, const vector<int> &edge_cycle) { 52 | int sz = (int) edge_cycle.size(); 53 | vector<int> vertex_cycle; 54 | if (sz <= 2) { 55 | vertex_cycle.push_back(g.edges[edge_cycle[0]].from); 56 | if (sz == 2) { 57 | vertex_cycle.push_back(g.edges[edge_cycle[0]].to); 58 | } 59 | } else { 60 | for (int i = 0; i < sz; i++) { 61 | int j = (i + 1) % sz; 62 | auto &e = g.edges[edge_cycle[i]]; 63 | auto &other = g.edges[edge_cycle[j]]; 64 | if (other.from == e.from || other.to == e.from) { 65 | vertex_cycle.push_back(e.to); 66 | } else { 67 | vertex_cycle.push_back(e.from); 68 | } 69 | } 70 | } 71 | return vertex_cycle; 72 | // only for simple cycles! 73 | } -------------------------------------------------------------------------------- /graph/dfs_digraph_useless.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class dfs_digraph : public digraph<T> { 3 | public: 4 | using digraph<T>::edges; 5 | using digraph<T>::g; 6 | using digraph<T>::n; 7 | using digraph<T>::ignore; 8 | 9 | vector<int> pv; 10 | vector<int> pe; 11 | vector<int> order; 12 | vector<int> pos; 13 | vector<int> end; 14 | vector<int> sz; 15 | vector<int> root; 16 | vector<int> depth; 17 | vector<T> dist; 18 | 19 | dfs_digraph(int _n) : digraph<T>(_n) { 20 | } 21 | 22 | void clear() { 23 | pv.clear(); 24 | pe.clear(); 25 | order.clear(); 26 | pos.clear(); 27 | end.clear(); 28 | sz.clear(); 29 | root.clear(); 30 | depth.clear(); 31 | dist.clear(); 32 | } 33 | 34 | void init() { 35 | pv = vector<int>(n, -1); 36 | pe = vector<int>(n, -1); 37 | order.clear(); 38 | pos = vector<int>(n, -1); 39 | end = vector<int>(n, -1); 40 | sz = vector<int>(n, 0); 41 | root = vector<int>(n, -1); 42 | depth = vector<int>(n, -1); 43 | dist = vector<T>(n); 44 | } 45 | 46 | private: 47 | void do_dfs(int v) { 48 | pos[v] = (int) order.size(); 49 | order.push_back(v); 50 | sz[v] = 1; 51 | for (int id : g[v]) { 52 | if (id == pe[v] || (ignore != nullptr && ignore(id))) { 53 | continue; 54 | } 55 | auto &e = edges[id]; 56 | int to = e.from ^ e.to ^ v; 57 | // well, this is controversial... 58 | if (depth[to] != -1) { 59 | continue; 60 | } 61 | depth[to] = depth[v] + 1; 62 | dist[to] = dist[v] + e.cost; 63 | pv[to] = v; 64 | pe[to] = id; 65 | root[to] = (root[v] != -1 ? root[v] : to); 66 | do_dfs(to); 67 | sz[v] += sz[to]; 68 | } 69 | end[v] = (int) order.size() - 1; 70 | } 71 | 72 | void do_dfs_from(int v) { 73 | depth[v] = 0; 74 | dist[v] = T{}; 75 | root[v] = v; 76 | pv[v] = pe[v] = -1; 77 | do_dfs(v); 78 | } 79 | 80 | public: 81 | int dfs_one_unsafe(int v) { 82 | // run init() before this 83 | // then run this with the required v's 84 | do_dfs_from(v); 85 | return v; 86 | } 87 | 88 | int dfs(int v) { 89 | init(); 90 | do_dfs_from(v); 91 | // assert((int) order.size() == n); 92 | return v; 93 | } 94 | 95 | void dfs_many(const vector<int> &roots) { 96 | init(); 97 | for (int v : roots) { 98 | if (depth[v] == -1) { 99 | do_dfs_from(v); 100 | } 101 | } 102 | // assert((int) order.size() == n); 103 | } 104 | 105 | vector<int> dfs_all() { 106 | init(); 107 | vector<int> roots; 108 | for (int v = 0; v < n; v++) { 109 | if (depth[v] == -1) { 110 | roots.push_back(v); 111 | do_dfs_from(v); 112 | } 113 | } 114 | assert((int) order.size() == n); 115 | return roots; 116 | } 117 | }; -------------------------------------------------------------------------------- /graph/dfs_forest.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class dfs_forest : public forest<T> { 3 | public: 4 | using forest<T>::edges; 5 | using forest<T>::g; 6 | using forest<T>::n; 7 | using forest<T>::ignore; 8 | 9 | vector<int> pv; 10 | vector<int> pe; 11 | vector<int> order; 12 | vector<int> pos; 13 | vector<int> end; 14 | vector<int> sz; 15 | vector<int> root; 16 | vector<int> depth; 17 | vector<T> dist; 18 | 19 | dfs_forest(int _n) : forest<T>(_n) { 20 | } 21 | 22 | void init() { 23 | pv = vector<int>(n, -1); 24 | pe = vector<int>(n, -1); 25 | order.clear(); 26 | pos = vector<int>(n, -1); 27 | end = vector<int>(n, -1); 28 | sz = vector<int>(n, 0); 29 | root = vector<int>(n, -1); 30 | depth = vector<int>(n, -1); 31 | dist = vector<T>(n); 32 | } 33 | 34 | void clear() { 35 | pv.clear(); 36 | pe.clear(); 37 | order.clear(); 38 | pos.clear(); 39 | end.clear(); 40 | sz.clear(); 41 | root.clear(); 42 | depth.clear(); 43 | dist.clear(); 44 | } 45 | 46 | private: 47 | void do_dfs(int v) { 48 | pos[v] = (int) order.size(); 49 | order.push_back(v); 50 | sz[v] = 1; 51 | for (int id : g[v]) { 52 | if (id == pe[v] || (ignore != nullptr && ignore(id))) { 53 | continue; 54 | } 55 | auto &e = edges[id]; 56 | int to = e.from ^ e.to ^ v; 57 | depth[to] = depth[v] + 1; 58 | dist[to] = dist[v] + e.cost; 59 | pv[to] = v; 60 | pe[to] = id; 61 | root[to] = (root[v] != -1 ? root[v] : to); 62 | do_dfs(to); 63 | sz[v] += sz[to]; 64 | } 65 | end[v] = (int) order.size() - 1; 66 | } 67 | 68 | void do_dfs_from(int v) { 69 | depth[v] = 0; 70 | dist[v] = T{}; 71 | root[v] = v; 72 | pv[v] = pe[v] = -1; 73 | do_dfs(v); 74 | } 75 | 76 | public: 77 | void dfs(int v, bool clear_order = true) { 78 | if (pv.empty()) { 79 | init(); 80 | } else { 81 | if (clear_order) { 82 | order.clear(); 83 | } 84 | } 85 | do_dfs_from(v); 86 | } 87 | 88 | void dfs_all() { 89 | init(); 90 | for (int v = 0; v < n; v++) { 91 | if (depth[v] == -1) { 92 | do_dfs_from(v); 93 | } 94 | } 95 | assert((int) order.size() == n); 96 | } 97 | }; -------------------------------------------------------------------------------- /graph/dfs_undigraph.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class dfs_undigraph : public undigraph<T> { 3 | public: 4 | using undigraph<T>::edges; 5 | using undigraph<T>::g; 6 | using undigraph<T>::n; 7 | using undigraph<T>::ignore; 8 | 9 | vector<int> pv; 10 | vector<int> pe; 11 | vector<int> order; 12 | vector<int> pos; 13 | vector<int> end; 14 | vector<int> sz; 15 | vector<int> root; 16 | vector<int> depth; 17 | vector<int> min_depth; 18 | vector<T> dist; 19 | vector<int> was; 20 | int attempt; 21 | 22 | dfs_undigraph(int _n) : undigraph<T>(_n) { 23 | } 24 | 25 | void init() { 26 | pv = vector<int>(n, -1); 27 | pe = vector<int>(n, -1); 28 | order.clear(); 29 | pos = vector<int>(n, -1); 30 | end = vector<int>(n, -1); 31 | sz = vector<int>(n, 0); 32 | root = vector<int>(n, -1); 33 | depth = vector<int>(n, -1); 34 | min_depth = vector<int>(n, -1); 35 | dist = vector<T>(n); 36 | was = vector<int>(n, -1); 37 | attempt = 0; 38 | } 39 | 40 | void clear() { 41 | pv.clear(); 42 | pe.clear(); 43 | order.clear(); 44 | pos.clear(); 45 | end.clear(); 46 | sz.clear(); 47 | root.clear(); 48 | depth.clear(); 49 | min_depth.clear(); 50 | dist.clear(); 51 | was.clear(); 52 | } 53 | 54 | private: 55 | void do_dfs(int v) { 56 | was[v] = attempt; 57 | pos[v] = (int) order.size(); 58 | order.push_back(v); 59 | sz[v] = 1; 60 | min_depth[v] = depth[v]; 61 | for (int id : g[v]) { 62 | if (id == pe[v] || (ignore != nullptr && ignore(id))) { 63 | continue; 64 | } 65 | auto &e = edges[id]; 66 | int to = e.from ^ e.to ^ v; 67 | if (was[to] == attempt) { 68 | min_depth[v] = min(min_depth[v], depth[to]); 69 | continue; 70 | } 71 | depth[to] = depth[v] + 1; 72 | dist[to] = dist[v] + e.cost; 73 | pv[to] = v; 74 | pe[to] = id; 75 | root[to] = (root[v] != -1 ? root[v] : to); 76 | do_dfs(to); 77 | sz[v] += sz[to]; 78 | min_depth[v] = min(min_depth[v], min_depth[to]); 79 | } 80 | end[v] = (int) order.size() - 1; 81 | } 82 | 83 | void do_dfs_from(int v) { 84 | ++attempt; 85 | depth[v] = 0; 86 | dist[v] = T{}; 87 | root[v] = v; 88 | pv[v] = pe[v] = -1; 89 | do_dfs(v); 90 | } 91 | 92 | public: 93 | void dfs(int v, bool clear_order = true) { 94 | if (pv.empty()) { 95 | init(); 96 | } else { 97 | if (clear_order) { 98 | order.clear(); 99 | } 100 | } 101 | do_dfs_from(v); 102 | } 103 | 104 | void dfs_all() { 105 | init(); 106 | for (int v = 0; v < n; v++) { 107 | if (depth[v] == -1) { 108 | do_dfs_from(v); 109 | } 110 | } 111 | assert((int) order.size() == n); 112 | } 113 | }; -------------------------------------------------------------------------------- /graph/digraph.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class digraph : public graph<T> { 3 | public: 4 | using graph<T>::edges; 5 | using graph<T>::g; 6 | using graph<T>::n; 7 | using graph<T>::ignore; 8 | 9 | digraph(int _n) : graph<T>(_n) { 10 | } 11 | 12 | int add(int from, int to, T cost = 1) { 13 | assert(0 <= from && from < n && 0 <= to && to < n); 14 | int id = (int) edges.size(); 15 | g[from].push_back(id); 16 | edges.push_back({from, to, cost}); 17 | return id; 18 | } 19 | 20 | digraph<T> reverse() const { 21 | digraph<T> rev(n); 22 | for (auto &e : edges) { 23 | rev.add(e.to, e.from, e.cost); 24 | } 25 | if (ignore != nullptr) { 26 | rev.set_ignore_edge_rule([&](int id) { 27 | return ignore(id); 28 | }); 29 | } 30 | return rev; 31 | } 32 | }; -------------------------------------------------------------------------------- /graph/dijkstra-set.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector <T> dijkstra(const graph<T> &g, int start) { 3 | assert(0 <= start && start < g.n); 4 | vector<T> dist(g.n, numeric_limits<T>::max()); 5 | dist[start] = 0; 6 | set< pair<T, int> > s; 7 | s.emplace(dist[start], start); 8 | while (!s.empty()) { 9 | int i = s.begin()->second; 10 | s.erase(s.begin()); 11 | for (int id : g.g[i]) { 12 | if (g.ignore != nullptr && g.ignore(id)) { 13 | continue; 14 | } 15 | auto &e = g.edges[id]; 16 | int to = e.from ^ e.to ^ i; 17 | if (dist[i] + e.cost < dist[to]) { 18 | s.erase({dist[to], to}); 19 | dist[to] = dist[i] + e.cost; 20 | s.emplace(dist[to], to); 21 | } 22 | } 23 | } 24 | return dist; 25 | // returns numeric_limits<T>::max() if there's no path 26 | } -------------------------------------------------------------------------------- /graph/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector <T> dijkstra(const graph<T> &g, int start) { 3 | assert(0 <= start && start < g.n); 4 | vector<T> dist(g.n, numeric_limits<T>::max()); 5 | priority_queue<pair<T, int>, vector<pair<T, int> >, greater<pair<T, int> > > s; 6 | dist[start] = 0; 7 | s.emplace(dist[start], start); 8 | while (!s.empty()) { 9 | T expected = s.top().first; 10 | int i = s.top().second; 11 | s.pop(); 12 | if (dist[i] != expected) { 13 | continue; 14 | } 15 | for (int id : g.g[i]) { 16 | if (g.ignore != nullptr && g.ignore(id)) { 17 | continue; 18 | } 19 | auto &e = g.edges[id]; 20 | int to = e.from ^ e.to ^ i; 21 | if (dist[i] + e.cost < dist[to]) { 22 | dist[to] = dist[i] + e.cost; 23 | s.emplace(dist[to], to); 24 | } 25 | } 26 | } 27 | return dist; 28 | // returns numeric_limits<T>::max() if there's no path 29 | } -------------------------------------------------------------------------------- /graph/dominators.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> find_dominators(const digraph<T> &g, int root) { 3 | int n = g.n; 4 | vector<int> pos(n, -1); 5 | vector<int> order; 6 | vector<int> parent(n, -1); 7 | function<void(int)> dfs = [&g, &pos, &order, &parent, &dfs](int v) { 8 | pos[v] = (int) order.size(); 9 | order.push_back(v); 10 | for (int id : g.g[v]) { 11 | if (g.ignore != nullptr && g.ignore(id)) { 12 | continue; 13 | } 14 | auto &e = g.edges[id]; 15 | int u = e.to; 16 | if (pos[u] == -1) { 17 | parent[u] = v; 18 | dfs(u); 19 | } 20 | } 21 | }; 22 | dfs(root); 23 | vector<int> p(n), best(n); 24 | iota(p.begin(), p.end(), 0); 25 | iota(best.begin(), best.end(), 0); 26 | vector<int> sdom = pos; 27 | function<int(int)> find_best = [&p, &best, &sdom, &find_best](int x) { 28 | if (p[x] != x) { 29 | int u = find_best(p[x]); 30 | if (sdom[u] < sdom[best[x]]) { 31 | best[x] = u; 32 | } 33 | p[x] = p[p[x]]; 34 | } 35 | if (sdom[best[p[x]]] < sdom[best[x]]) { 36 | best[x] = best[p[x]]; 37 | } 38 | return best[x]; 39 | }; 40 | digraph<int> g_rev = g.reverse(); 41 | vector<int> idom(n, -1); 42 | vector<int> link(n, 0); 43 | vector< vector<int> > bucket(n); 44 | for (int it = (int) order.size() - 1; it >= 0; it--) { 45 | int w = order[it]; 46 | for (int id : g_rev.g[w]) { 47 | if (g_rev.ignore != nullptr && g_rev.ignore(id)) { 48 | continue; 49 | } 50 | auto &e = g_rev.edges[id]; 51 | int u = e.to; 52 | sdom[w] = min(sdom[w], sdom[find_best(u)]); 53 | } 54 | idom[w] = order[sdom[w]]; 55 | for (int u : bucket[w]) { 56 | link[u] = find_best(u); 57 | } 58 | for (int id : g.g[w]) { 59 | if (g.ignore != nullptr && g.ignore(id)) { 60 | continue; 61 | } 62 | auto &e = g.edges[id]; 63 | int u = e.to; 64 | if (parent[u] == w) { 65 | p[u] = w; 66 | } 67 | } 68 | bucket[order[sdom[w]]].push_back(w); 69 | } 70 | for (int it = 1; it < (int) order.size(); it++) { 71 | int w = order[it]; 72 | idom[w] = idom[link[w]]; 73 | } 74 | return idom; 75 | // idom[i] -- immediate dominator for vertex i 76 | } -------------------------------------------------------------------------------- /graph/eulerian.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nealwu/algo/9f69209c3af0ff268381f5b292f788418f910bdd/graph/eulerian.cpp -------------------------------------------------------------------------------- /graph/forest.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class forest : public graph<T> { 3 | public: 4 | using graph<T>::edges; 5 | using graph<T>::g; 6 | using graph<T>::n; 7 | 8 | forest(int _n) : graph<T>(_n) { 9 | } 10 | 11 | int add(int from, int to, T cost = 1) { 12 | assert(0 <= from && from < n && 0 <= to && to < n); 13 | int id = (int) edges.size(); 14 | assert(id < n - 1); 15 | g[from].push_back(id); 16 | g[to].push_back(id); 17 | edges.push_back({from, to, cost}); 18 | return id; 19 | } 20 | }; -------------------------------------------------------------------------------- /graph/graph.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class graph { 3 | public: 4 | struct edge { 5 | int from; 6 | int to; 7 | T cost; 8 | }; 9 | 10 | vector<edge> edges; 11 | vector< vector<int> > g; 12 | int n; 13 | 14 | function<bool(int)> ignore; 15 | 16 | graph(int _n) : n(_n) { 17 | g.resize(n); 18 | ignore = nullptr; 19 | } 20 | 21 | virtual int add(int from, int to, T cost) = 0; 22 | 23 | virtual void set_ignore_edge_rule(const function<bool(int)> &f) { 24 | ignore = f; 25 | } 26 | 27 | virtual void reset_ignore_edge_rule() { 28 | ignore = nullptr; 29 | } 30 | }; -------------------------------------------------------------------------------- /graph/hld_forest.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class hld_forest : public lca_forest<T> { 3 | public: 4 | using lca_forest<T>::edges; 5 | using lca_forest<T>::g; 6 | using lca_forest<T>::n; 7 | using lca_forest<T>::ignore; 8 | using lca_forest<T>::pv; 9 | using lca_forest<T>::sz; 10 | using lca_forest<T>::pos; 11 | using lca_forest<T>::order; 12 | using lca_forest<T>::depth; 13 | using lca_forest<T>::dfs; 14 | using lca_forest<T>::dfs_all; 15 | using lca_forest<T>::lca; 16 | using lca_forest<T>::build_lca; 17 | 18 | vector<int> head; 19 | vector<int> visited; 20 | 21 | hld_forest(int _n) : lca_forest<T>(_n) { 22 | visited.resize(n); 23 | } 24 | 25 | void build_hld(const vector<int> &vs) { 26 | for (int tries = 0; tries < 2; tries++) { 27 | if (vs.empty()) { 28 | dfs_all(); 29 | } else { 30 | order.clear(); 31 | for (int v : vs) { 32 | assert(depth[v] == -1); 33 | dfs(v, false); 34 | } 35 | assert((int) order.size() == n); 36 | } 37 | if (tries == 1) { 38 | break; 39 | } 40 | for (int i = 0; i < n; i++) { 41 | if (g[i].empty()) { 42 | continue; 43 | } 44 | int best = -1, bid = 0; 45 | for (int j = 0; j < (int) g[i].size(); j++) { 46 | int id = g[i][j]; 47 | if (ignore != nullptr && ignore(id)) { 48 | continue; 49 | } 50 | int v = edges[id].from ^ edges[id].to ^ i; 51 | if (pv[v] != i) { 52 | continue; 53 | } 54 | if (sz[v] > best) { 55 | best = sz[v]; 56 | bid = j; 57 | } 58 | } 59 | swap(g[i][0], g[i][bid]); 60 | } 61 | } 62 | build_lca(); 63 | head.resize(n); 64 | for (int i = 0; i < n; i++) { 65 | head[i] = i; 66 | } 67 | for (int i = 0; i < n - 1; i++) { 68 | int x = order[i]; 69 | int y = order[i + 1]; 70 | if (pv[y] == x) { 71 | head[y] = head[x]; 72 | } 73 | } 74 | } 75 | 76 | void build_hld(int v) { 77 | build_hld(vector<int>(1, v)); 78 | } 79 | 80 | void build_hld_all() { 81 | build_hld(vector<int>()); 82 | } 83 | 84 | /* 85 | vector< pair<int, int> > get_path(int x, int y) { 86 | vector< pair<int, int> > path[2]; 87 | int z = lca(x, y); 88 | for (int id = 0; id < 2; id++) { 89 | int v = (id == 0 ? x : y); 90 | while (v != z) { 91 | if (depth[head[v]] <= depth[z]) { 92 | path[id].emplace_back(pos[z] + 1, pos[v]); 93 | break; 94 | } 95 | path[id].emplace_back(pos[head[v]], pos[v]); 96 | v = pv[head[v]]; 97 | } 98 | } 99 | vector< pair<int, int> > ret; 100 | for (int i = 0; i < (int) path[0].size(); i++) { 101 | ret.emplace_back(path[0][i].second, path[0][i].first); 102 | } 103 | ret.emplace_back(-1, pos[z]); 104 | for (int i = (int) path[1].size() - 1; i >= 0; i--) { 105 | ret.push_back(path[1][i]); 106 | } 107 | return ret; 108 | // returns segments of the path: 109 | // first from x to lca, reversed segments 110 | // then (-1, pos[lca]) 111 | // then from lca to y, direct segments 112 | // but in most cases, apply_on_path should be enough 113 | } 114 | */ 115 | 116 | bool apply_on_path(int x, int y, bool with_lca, function<void(int,int,bool)> f) { 117 | // f(x, y, up): up -- whether this part of the path goes up 118 | assert(!head.empty()); 119 | int z = lca(x, y); 120 | if (z == -1) { 121 | return false; 122 | } 123 | { 124 | int v = x; 125 | while (v != z) { 126 | if (depth[head[v]] <= depth[z]) { 127 | f(pos[z] + 1, pos[v], true); 128 | break; 129 | } 130 | f(pos[head[v]], pos[v], true); 131 | v = pv[head[v]]; 132 | } 133 | } 134 | if (with_lca) { 135 | f(pos[z], pos[z], false); 136 | } 137 | { 138 | int v = y; 139 | int cnt_visited = 0; 140 | while (v != z) { 141 | if (depth[head[v]] <= depth[z]) { 142 | f(pos[z] + 1, pos[v], false); 143 | break; 144 | } 145 | visited[cnt_visited++] = v; 146 | v = pv[head[v]]; 147 | } 148 | for (int at = cnt_visited - 1; at >= 0; at--) { 149 | v = visited[at]; 150 | f(pos[head[v]], pos[v], false); 151 | } 152 | } 153 | return true; 154 | } 155 | }; -------------------------------------------------------------------------------- /graph/lca_forest.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class lca_forest : public dfs_forest<T> { 3 | public: 4 | using dfs_forest<T>::edges; 5 | using dfs_forest<T>::g; 6 | using dfs_forest<T>::n; 7 | using dfs_forest<T>::pv; 8 | using dfs_forest<T>::pos; 9 | using dfs_forest<T>::end; 10 | using dfs_forest<T>::depth; 11 | 12 | int h; 13 | vector< vector<int> > pr; 14 | 15 | lca_forest(int _n) : dfs_forest<T>(_n) { 16 | } 17 | 18 | inline void build_lca() { 19 | assert(!pv.empty()); 20 | int max_depth = 0; 21 | for (int i = 0; i < n; i++) { 22 | max_depth = max(max_depth, depth[i]); 23 | } 24 | h = 1; 25 | while ((1 << h) <= max_depth) { 26 | h++; 27 | } 28 | pr.resize(n); 29 | for (int i = 0; i < n; i++) { 30 | pr[i].resize(h); 31 | pr[i][0] = pv[i]; 32 | } 33 | for (int j = 1; j < h; j++) { 34 | for (int i = 0; i < n; i++) { 35 | pr[i][j] = (pr[i][j - 1] == -1 ? -1 : pr[pr[i][j - 1]][j - 1]); 36 | } 37 | } 38 | } 39 | 40 | inline bool anc(int x, int y) { 41 | return (pos[x] <= pos[y] && end[y] <= end[x]); 42 | } 43 | 44 | inline int lca(int x, int y) { 45 | // maybe optimize? 46 | // if depth[x] > depth[y], swap 47 | // then go from j = log(depth[x])? 48 | assert(!pr.empty()); 49 | if (anc(x, y)) { 50 | return x; 51 | } 52 | if (anc(y, x)) { 53 | return y; 54 | } 55 | for (int j = h - 1; j >= 0; j--) { 56 | if (pr[x][j] != -1 && !anc(pr[x][j], y)) { 57 | x = pr[x][j]; 58 | } 59 | } 60 | return pr[x][0]; 61 | } 62 | }; -------------------------------------------------------------------------------- /graph/mst.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> find_mst(const undigraph<T> &g, T &ans) { 3 | vector<int> order(g.edges.size()); 4 | iota(order.begin(), order.end(), 0); 5 | sort(order.begin(), order.end(), [&g](int a, int b) { 6 | return g.edges[a].cost < g.edges[b].cost; 7 | }); 8 | dsu d(g.n); 9 | vector<int> ans_list; 10 | ans = 0; 11 | for (int id : order) { 12 | if (g.ignore != nullptr && g.ignore(id)) { 13 | continue; 14 | } 15 | auto &e = g.edges[id]; 16 | if (d.get(e.from) != d.get(e.to)) { 17 | d.unite(e.from, e.to); 18 | ans_list.push_back(id); 19 | ans += e.cost; 20 | } 21 | } 22 | return ans_list; 23 | // returns edge ids of minimum "spanning" forest 24 | } -------------------------------------------------------------------------------- /graph/scc.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> find_scc(const digraph<T> &g, int &cnt) { 3 | digraph<T> g_rev = g.reverse(); 4 | vector<int> order; 5 | vector<bool> was(g.n, false); 6 | function<void(int)> dfs1 = [&](int v) { 7 | was[v] = true; 8 | for (int id : g.g[v]) { 9 | if (g.ignore != nullptr && g.ignore(id)) { 10 | continue; 11 | } 12 | auto &e = g.edges[id]; 13 | int to = e.to; 14 | if (!was[to]) { 15 | dfs1(to); 16 | } 17 | } 18 | order.push_back(v); 19 | }; 20 | for (int i = 0; i < g.n; i++) { 21 | if (!was[i]) { 22 | dfs1(i); 23 | } 24 | } 25 | vector<int> c(g.n, -1); 26 | function<void(int)> dfs2 = [&](int v) { 27 | for (int id : g_rev.g[v]) { 28 | if (g_rev.ignore != nullptr && g_rev.ignore(id)) { 29 | continue; 30 | } 31 | auto &e = g_rev.edges[id]; 32 | int to = e.to; 33 | if (c[to] == -1) { 34 | c[to] = c[v]; 35 | dfs2(to); 36 | } 37 | } 38 | }; 39 | cnt = 0; 40 | for (int id = g.n - 1; id >= 0; id--) { 41 | int i = order[id]; 42 | if (c[i] != -1) { 43 | continue; 44 | } 45 | c[i] = cnt++; 46 | dfs2(i); 47 | } 48 | return c; 49 | // c[i] <= c[j] for every edge i -> j 50 | } -------------------------------------------------------------------------------- /graph/topsort.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> find_topsort(const digraph<T> &g) { 3 | vector<int> deg(g.n, 0); 4 | for (int id = 0; id < (int) g.edges.size(); id++) { 5 | if (g.ignore != nullptr && g.ignore(id)) { 6 | continue; 7 | } 8 | deg[g.edges[id].to]++; 9 | } 10 | vector<int> x; 11 | for (int i = 0; i < g.n; i++) { 12 | if (deg[i] == 0) { 13 | x.push_back(i); 14 | } 15 | } 16 | for (int ptr = 0; ptr < (int) x.size(); ptr++) { 17 | int i = x[ptr]; 18 | for (int id : g.g[i]) { 19 | if (g.ignore != nullptr && g.ignore(id)) { 20 | continue; 21 | } 22 | auto &e = g.edges[id]; 23 | int to = e.to; 24 | if (--deg[to] == 0) { 25 | x.push_back(to); 26 | } 27 | } 28 | } 29 | if ((int) x.size() != g.n) { 30 | return vector<int>(); 31 | } 32 | return x; 33 | } -------------------------------------------------------------------------------- /graph/twosat.cpp: -------------------------------------------------------------------------------- 1 | class twosat { 2 | public: 3 | digraph<int> g; 4 | int n; 5 | 6 | twosat(int _n) : g(digraph<int>(2 * _n)), n(_n) { 7 | } 8 | 9 | inline void add(int x, int value_x) { 10 | // (v[x] == value_x) 11 | assert(0 <= x && x < n); 12 | assert(0 <= value_x && value_x <= 1); 13 | g.add(2 * x + (value_x ^ 1), 2 * x + value_x); 14 | } 15 | 16 | inline void add(int x, int value_x, int y, int value_y) { 17 | // (v[x] == value_x || v[y] == value_y) 18 | assert(0 <= x && x < n && 0 <= y && y < n); 19 | assert(0 <= value_x && value_x <= 1 && 0 <= value_y && value_y <= 1); 20 | g.add(2 * x + (value_x ^ 1), 2 * y + value_y); 21 | g.add(2 * y + (value_y ^ 1), 2 * x + value_x); 22 | } 23 | 24 | inline vector<int> solve() { 25 | int cnt; 26 | vector<int> c = find_scc(g, cnt); 27 | vector<int> res(n); 28 | for (int i = 0; i < n; i++) { 29 | if (c[2 * i] == c[2 * i + 1]) { 30 | return vector<int>(); 31 | } 32 | res[i] = (c[2 * i] < c[2 * i + 1]); 33 | } 34 | return res; 35 | } 36 | }; -------------------------------------------------------------------------------- /graph/undigraph.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class undigraph : public graph<T> { 3 | public: 4 | using graph<T>::edges; 5 | using graph<T>::g; 6 | using graph<T>::n; 7 | 8 | undigraph(int _n) : graph<T>(_n) { 9 | } 10 | 11 | int add(int from, int to, T cost = 1) { 12 | assert(0 <= from && from < n && 0 <= to && to < n); 13 | int id = (int) edges.size(); 14 | g[from].push_back(id); 15 | g[to].push_back(id); 16 | edges.push_back({from, to, cost}); 17 | return id; 18 | } 19 | }; -------------------------------------------------------------------------------- /misc/debug.cpp: -------------------------------------------------------------------------------- 1 | string to_string(string s) { 2 | return '"' + s + '"'; 3 | } 4 | 5 | string to_string(const char* s) { 6 | return to_string((string) s); 7 | } 8 | 9 | string to_string(bool b) { 10 | return (b ? "true" : "false"); 11 | } 12 | 13 | template <typename A, typename B> 14 | string to_string(pair<A, B> p) { 15 | return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; 16 | } 17 | 18 | template <typename A> 19 | string to_string(A v) { 20 | bool first = true; 21 | string res = "{"; 22 | for (const auto &x : v) { 23 | if (!first) { 24 | res += ", "; 25 | } 26 | first = false; 27 | res += to_string(x); 28 | } 29 | res += "}"; 30 | return res; 31 | } 32 | 33 | void debug_out() { cerr << endl; } 34 | 35 | template <typename Head, typename... Tail> 36 | void debug_out(Head H, Tail... T) { 37 | cerr << " " << to_string(H); 38 | debug_out(T...); 39 | } 40 | 41 | #ifdef LOCAL 42 | #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__) 43 | #else 44 | #define debug(...) 42 45 | #endif -------------------------------------------------------------------------------- /misc/lis.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | int lis(const vector<T> &a) { 3 | vector<T> u; 4 | for (const T &x : a) { 5 | auto it = lower_bound(u.begin(), u.end(), x); 6 | if (it == u.end()) { 7 | u.push_back(x); 8 | } else { 9 | *it = x; 10 | } 11 | } 12 | return (int) u.size(); 13 | } -------------------------------------------------------------------------------- /numeric/bm.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<T> BM(vector<T> a) { 3 | vector<T> p = {1}; 4 | vector<T> q = {1}; 5 | int l = 0; 6 | for (int r = 1; r <= (int) a.size(); r++) { 7 | T delta = 0; 8 | for (int j = 0; j <= l; j++) { 9 | delta += a[r - 1 - j] * p[j]; 10 | } 11 | q.insert(q.begin(), 0); 12 | if (delta != 0) { 13 | vector<T> t = p; 14 | if (q.size() > t.size()) { 15 | t.resize(q.size()); 16 | } 17 | for (int i = 0; i < (int) q.size(); i++) { 18 | t[i] -= delta * q[i]; 19 | } 20 | if (2 * l <= r - 1) { 21 | q = p; 22 | T od = 1 / delta; 23 | for (T& x : q) { 24 | x *= od; 25 | } 26 | l = r - l; 27 | } 28 | swap(p, t); 29 | } 30 | } 31 | assert((int) p.size() == l + 1); 32 | // assert(l * 2 + 30 < (int) a.size()); 33 | reverse(p.begin(), p.end()); 34 | return p; 35 | } -------------------------------------------------------------------------------- /numeric/extgcd.cpp: -------------------------------------------------------------------------------- 1 | template<typename T> 2 | T extgcd(T a, T b, T &x, T &y) { 3 | if (a == 0) { 4 | x = 0; 5 | y = 1; 6 | return b; 7 | } 8 | T p = b / a; 9 | T g = extgcd(b - p * a, a, y, x); 10 | x -= p * y; 11 | return g; 12 | } 13 | 14 | template<typename T> 15 | bool diophantine(T a, T b, T c, T &x, T &y, T &g) { 16 | if (a == 0 && b == 0) { 17 | if (c == 0) { 18 | x = y = g = 0; 19 | return true; 20 | } 21 | return false; 22 | } 23 | if (a == 0) { 24 | if (c % b == 0) { 25 | x = 0; 26 | y = c / b; 27 | g = abs(b); 28 | return true; 29 | } 30 | return false; 31 | } 32 | if (b == 0) { 33 | if (c % a == 0) { 34 | x = c / a; 35 | y = 0; 36 | g = abs(a); 37 | return true; 38 | } 39 | return false; 40 | } 41 | g = extgcd(a, b, x, y); 42 | if (c % g != 0) { 43 | return false; 44 | } 45 | T dx = c / a; 46 | c -= dx * a; 47 | T dy = c / b; 48 | c -= dy * b; 49 | x = dx + (T) ((__int128) x * (c / g) % b); 50 | y = dy + (T) ((__int128) y * (c / g) % a); 51 | g = abs(g); 52 | return true; 53 | // |x|, |y| <= max(|a|, |b|, |c|) [tested] 54 | } 55 | 56 | bool crt(long long k1, long long m1, long long k2, long long m2, long long &k, long long &m) { 57 | k1 %= m1; 58 | if (k1 < 0) k1 += m1; 59 | k2 %= m2; 60 | if (k2 < 0) k2 += m2; 61 | long long x, y, g; 62 | if (!diophantine(m1, -m2, k2 - k1, x, y, g)) { 63 | return false; 64 | } 65 | long long dx = m2 / g; 66 | long long delta = x / dx - (x % dx < 0); 67 | k = m1 * (x - dx * delta) + k1; 68 | m = m1 / g * m2; 69 | assert(0 <= k && k < m); 70 | return true; 71 | } -------------------------------------------------------------------------------- /numeric/factorizer.cpp: -------------------------------------------------------------------------------- 1 | namespace factorizer { 2 | 3 | template <typename T> 4 | struct FactorizerVarMod { static T value; }; 5 | template <typename T> 6 | T FactorizerVarMod<T>::value; 7 | 8 | template <typename T> 9 | bool IsPrime(T n, const vector<T>& bases) { 10 | if (n < 2) { 11 | return false; 12 | } 13 | vector<T> small_primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; 14 | for (const T& x : small_primes) { 15 | if (n % x == 0) { 16 | return n == x; 17 | } 18 | } 19 | if (n < 31 * 31) { 20 | return true; 21 | } 22 | int s = 0; 23 | T d = n - 1; 24 | while ((d & 1) == 0) { 25 | d >>= 1; 26 | s++; 27 | } 28 | FactorizerVarMod<T>::value = n; 29 | for (const T& a : bases) { 30 | if (a % n == 0) { 31 | continue; 32 | } 33 | Modular<FactorizerVarMod<T>> cur = a; 34 | cur = power(cur, d); 35 | if (cur == 1) { 36 | continue; 37 | } 38 | bool witness = true; 39 | for (int r = 0; r < s; r++) { 40 | if (cur == n - 1) { 41 | witness = false; 42 | break; 43 | } 44 | cur *= cur; 45 | } 46 | if (witness) { 47 | return false; 48 | } 49 | } 50 | return true; 51 | } 52 | 53 | bool IsPrime(int64_t n) { 54 | return IsPrime(n, {2, 325, 9375, 28178, 450775, 9780504, 1795265022}); 55 | } 56 | 57 | bool IsPrime(int32_t n) { 58 | return IsPrime(n, {2, 7, 61}); 59 | } 60 | 61 | // but if you really need uint64_t version... 62 | /* 63 | bool IsPrime(uint64_t n) { 64 | if (n < 2) { 65 | return false; 66 | } 67 | vector<uint32_t> small_primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; 68 | for (uint32_t x : small_primes) { 69 | if (n == x) { 70 | return true; 71 | } 72 | if (n % x == 0) { 73 | return false; 74 | } 75 | } 76 | if (n < 31 * 31) { 77 | return true; 78 | } 79 | uint32_t s = __builtin_ctzll(n - 1); 80 | uint64_t d = (n - 1) >> s; 81 | function<bool(uint64_t)> witness = [&n, &s, &d](uint64_t a) { 82 | uint64_t cur = 1, p = d; 83 | while (p > 0) { 84 | if (p & 1) { 85 | cur = (__uint128_t) cur * a % n; 86 | } 87 | a = (__uint128_t) a * a % n; 88 | p >>= 1; 89 | } 90 | if (cur == 1) { 91 | return false; 92 | } 93 | for (uint32_t r = 0; r < s; r++) { 94 | if (cur == n - 1) { 95 | return false; 96 | } 97 | cur = (__uint128_t) cur * cur % n; 98 | } 99 | return true; 100 | }; 101 | vector<uint64_t> bases_64bit = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}; 102 | for (uint64_t a : bases_64bit) { 103 | if (a % n == 0) { 104 | return true; 105 | } 106 | if (witness(a)) { 107 | return false; 108 | } 109 | } 110 | return true; 111 | } 112 | */ 113 | 114 | vector<int> least = {0, 1}; 115 | vector<int> primes; 116 | int precalculated = 1; 117 | 118 | void RunLinearSieve(int n) { 119 | n = max(n, 1); 120 | least.assign(n + 1, 0); 121 | primes.clear(); 122 | for (int i = 2; i <= n; i++) { 123 | if (least[i] == 0) { 124 | least[i] = i; 125 | primes.push_back(i); 126 | } 127 | for (int x : primes) { 128 | if (x > least[i] || i * x > n) { 129 | break; 130 | } 131 | least[i * x] = x; 132 | } 133 | } 134 | precalculated = n; 135 | } 136 | 137 | void RunSlowSieve(int n) { 138 | n = max(n, 1); 139 | least.assign(n + 1, 0); 140 | for (int i = 2; i * i <= n; i++) { 141 | if (least[i] == 0) { 142 | for (int j = i * i; j <= n; j += i) { 143 | if (least[j] == 0) { 144 | least[j] = i; 145 | } 146 | } 147 | } 148 | } 149 | primes.clear(); 150 | for (int i = 2; i <= n; i++) { 151 | if (least[i] == 0) { 152 | least[i] = i; 153 | primes.push_back(i); 154 | } 155 | } 156 | precalculated = n; 157 | } 158 | 159 | void RunSieve(int n) { 160 | RunLinearSieve(n); 161 | } 162 | 163 | template <typename T> 164 | vector<pair<T, int>> MergeFactors(const vector<pair<T, int>>& a, const vector<pair<T, int>>& b) { 165 | vector<pair<T, int>> c; 166 | int i = 0; 167 | int j = 0; 168 | while (i < (int) a.size() || j < (int) b.size()) { 169 | if (i < (int) a.size() && j < (int) b.size() && a[i].first == b[j].first) { 170 | c.emplace_back(a[i].first, a[i].second + b[j].second); 171 | ++i; 172 | ++j; 173 | continue; 174 | } 175 | if (j == (int) b.size() || (i < (int) a.size() && a[i].first < b[j].first)) { 176 | c.push_back(a[i++]); 177 | } else { 178 | c.push_back(b[j++]); 179 | } 180 | } 181 | return c; 182 | } 183 | 184 | template <typename T> 185 | vector<pair<T, int>> RhoC(const T& n, const T& c) { 186 | if (n <= 1) { 187 | return {}; 188 | } 189 | if ((n & 1) == 0) { 190 | return MergeFactors({{2, 1}}, RhoC(n / 2, c)); 191 | } 192 | if (IsPrime(n)) { 193 | return {{n, 1}}; 194 | } 195 | FactorizerVarMod<T>::value = n; 196 | Modular<FactorizerVarMod<T>> x = 2; 197 | Modular<FactorizerVarMod<T>> saved = 2; 198 | T power = 1; 199 | T lam = 1; 200 | while (true) { 201 | x = x * x + c; 202 | T g = __gcd((x - saved)(), n); 203 | if (g != 1) { 204 | return MergeFactors(RhoC(g, c + 1), RhoC(n / g, c + 1)); 205 | } 206 | if (power == lam) { 207 | saved = x; 208 | power <<= 1; 209 | lam = 0; 210 | } 211 | lam++; 212 | } 213 | return {}; 214 | } 215 | 216 | template <typename T> 217 | vector<pair<T, int>> Rho(const T& n) { 218 | return RhoC(n, static_cast<T>(1)); 219 | } 220 | 221 | template <typename T> 222 | vector<pair<T, int>> Factorize(T x) { 223 | if (x <= 1) { 224 | return {}; 225 | } 226 | if (x <= precalculated) { 227 | vector<pair<T, int>> ret; 228 | while (x > 1) { 229 | if (!ret.empty() && ret.back().first == least[x]) { 230 | ret.back().second++; 231 | } else { 232 | ret.emplace_back(least[x], 1); 233 | } 234 | x /= least[x]; 235 | } 236 | return ret; 237 | } 238 | if (x <= static_cast<int64_t>(precalculated) * precalculated) { 239 | vector<pair<T, int>> ret; 240 | if (!IsPrime(x)) { 241 | for (T i : primes) { 242 | T t = x / i; 243 | if (i > t) { 244 | break; 245 | } 246 | if (x == t * i) { 247 | int cnt = 0; 248 | while (x % i == 0) { 249 | x /= i; 250 | cnt++; 251 | } 252 | ret.emplace_back(i, cnt); 253 | if (IsPrime(x)) { 254 | break; 255 | } 256 | } 257 | } 258 | } 259 | if (x > 1) { 260 | ret.emplace_back(x, 1); 261 | } 262 | return ret; 263 | } 264 | return Rho(x); 265 | } 266 | 267 | template <typename T> 268 | vector<T> BuildDivisorsFromFactors(const vector<pair<T, int>>& factors) { 269 | vector<T> divisors = {1}; 270 | for (auto& p : factors) { 271 | int sz = (int) divisors.size(); 272 | for (int i = 0; i < sz; i++) { 273 | T cur = divisors[i]; 274 | for (int j = 0; j < p.second; j++) { 275 | cur *= p.first; 276 | divisors.push_back(cur); 277 | } 278 | } 279 | } 280 | sort(divisors.begin(), divisors.end()); 281 | return divisors; 282 | } 283 | 284 | } // namespace factorizer -------------------------------------------------------------------------------- /numeric/fft.cpp: -------------------------------------------------------------------------------- 1 | // make it understandable one day... 2 | namespace fft { 3 | 4 | typedef double dbl; 5 | 6 | struct num { 7 | dbl x, y; 8 | num() { x = y = 0; } 9 | num(dbl x_, dbl y_) : x(x_), y(y_) {} 10 | }; 11 | 12 | inline num operator+(num a, num b) { return num(a.x + b.x, a.y + b.y); } 13 | inline num operator-(num a, num b) { return num(a.x - b.x, a.y - b.y); } 14 | inline num operator*(num a, num b) { return num(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } 15 | inline num conj(num a) { return num(a.x, -a.y); } 16 | 17 | int base = 1; 18 | vector<num> roots = {{0, 0}, {1, 0}}; 19 | vector<int> rev = {0, 1}; 20 | 21 | const dbl PI = static_cast<dbl>(acosl(-1.0)); 22 | 23 | void ensure_base(int nbase) { 24 | if (nbase <= base) { 25 | return; 26 | } 27 | rev.resize(1 << nbase); 28 | for (int i = 0; i < (1 << nbase); i++) { 29 | rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1)); 30 | } 31 | roots.resize(1 << nbase); 32 | while (base < nbase) { 33 | dbl angle = 2 * PI / (1 << (base + 1)); 34 | // num z(cos(angle), sin(angle)); 35 | for (int i = 1 << (base - 1); i < (1 << base); i++) { 36 | roots[i << 1] = roots[i]; 37 | // roots[(i << 1) + 1] = roots[i] * z; 38 | dbl angle_i = angle * (2 * i + 1 - (1 << base)); 39 | roots[(i << 1) + 1] = num(cos(angle_i), sin(angle_i)); 40 | } 41 | base++; 42 | } 43 | } 44 | 45 | void fft(vector<num>& a, int n = -1) { 46 | if (n == -1) { 47 | n = (int) a.size(); 48 | } 49 | assert((n & (n - 1)) == 0); 50 | int zeros = __builtin_ctz(n); 51 | ensure_base(zeros); 52 | int shift = base - zeros; 53 | for (int i = 0; i < n; i++) { 54 | if (i < (rev[i] >> shift)) { 55 | swap(a[i], a[rev[i] >> shift]); 56 | } 57 | } 58 | for (int k = 1; k < n; k <<= 1) { 59 | for (int i = 0; i < n; i += 2 * k) { 60 | for (int j = 0; j < k; j++) { 61 | num z = a[i + j + k] * roots[j + k]; 62 | a[i + j + k] = a[i + j] - z; 63 | a[i + j] = a[i + j] + z; 64 | } 65 | } 66 | } 67 | } 68 | 69 | vector<num> fa, fb; 70 | 71 | vector<int64_t> square(const vector<int>& a) { 72 | if (a.empty()) { 73 | return {}; 74 | } 75 | int need = (int) a.size() + (int) a.size() - 1; 76 | int nbase = 1; 77 | while ((1 << nbase) < need) nbase++; 78 | ensure_base(nbase); 79 | int sz = 1 << nbase; 80 | if ((sz >> 1) > (int) fa.size()) { 81 | fa.resize(sz >> 1); 82 | } 83 | for (int i = 0; i < (sz >> 1); i++) { 84 | int x = (2 * i < (int) a.size() ? a[2 * i] : 0); 85 | int y = (2 * i + 1 < (int) a.size() ? a[2 * i + 1] : 0); 86 | fa[i] = num(x, y); 87 | } 88 | fft(fa, sz >> 1); 89 | num r(1.0 / (sz >> 1), 0.0); 90 | for (int i = 0; i <= (sz >> 2); i++) { 91 | int j = ((sz >> 1) - i) & ((sz >> 1) - 1); 92 | num fe = (fa[i] + conj(fa[j])) * num(0.5, 0); 93 | num fo = (fa[i] - conj(fa[j])) * num(0, -0.5); 94 | num aux = fe * fe + fo * fo * roots[(sz >> 1) + i] * roots[(sz >> 1) + i]; 95 | num tmp = fe * fo; 96 | fa[i] = r * (conj(aux) + num(0, 2) * conj(tmp)); 97 | fa[j] = r * (aux + num(0, 2) * tmp); 98 | } 99 | fft(fa, sz >> 1); 100 | vector<int64_t> res(need); 101 | for (int i = 0; i < need; i++) { 102 | res[i] = llround(i % 2 == 0 ? fa[i >> 1].x : fa[i >> 1].y); 103 | } 104 | return res; 105 | } 106 | 107 | vector<int64_t> multiply(const vector<int>& a, const vector<int>& b) { 108 | if (a.empty() || b.empty()) { 109 | return {}; 110 | } 111 | if (a == b) { 112 | return square(a); 113 | } 114 | int need = (int) a.size() + (int) b.size() - 1; 115 | int nbase = 1; 116 | while ((1 << nbase) < need) nbase++; 117 | ensure_base(nbase); 118 | int sz = 1 << nbase; 119 | if (sz > (int) fa.size()) { 120 | fa.resize(sz); 121 | } 122 | for (int i = 0; i < sz; i++) { 123 | int x = (i < (int) a.size() ? a[i] : 0); 124 | int y = (i < (int) b.size() ? b[i] : 0); 125 | fa[i] = num(x, y); 126 | } 127 | fft(fa, sz); 128 | num r(0, -0.25 / (sz >> 1)); 129 | for (int i = 0; i <= (sz >> 1); i++) { 130 | int j = (sz - i) & (sz - 1); 131 | num z = (fa[j] * fa[j] - conj(fa[i] * fa[i])) * r; 132 | fa[j] = (fa[i] * fa[i] - conj(fa[j] * fa[j])) * r; 133 | fa[i] = z; 134 | } 135 | for (int i = 0; i < (sz >> 1); i++) { 136 | num A0 = (fa[i] + fa[i + (sz >> 1)]) * num(0.5, 0); 137 | num A1 = (fa[i] - fa[i + (sz >> 1)]) * num(0.5, 0) * roots[(sz >> 1) + i]; 138 | fa[i] = A0 + A1 * num(0, 1); 139 | } 140 | fft(fa, sz >> 1); 141 | vector<int64_t> res(need); 142 | for (int i = 0; i < need; i++) { 143 | res[i] = llround(i % 2 == 0 ? fa[i >> 1].x : fa[i >> 1].y); 144 | } 145 | return res; 146 | } 147 | 148 | vector<int> multiply_mod(const vector<int>& a, const vector<int>& b, int m) { 149 | if (a.empty() || b.empty()) { 150 | return {}; 151 | } 152 | int eq = (a.size() == b.size() && a == b); 153 | int need = (int) a.size() + (int) b.size() - 1; 154 | int nbase = 0; 155 | while ((1 << nbase) < need) nbase++; 156 | ensure_base(nbase); 157 | int sz = 1 << nbase; 158 | if (sz > (int) fa.size()) { 159 | fa.resize(sz); 160 | } 161 | for (int i = 0; i < (int) a.size(); i++) { 162 | int x = (a[i] % m + m) % m; 163 | fa[i] = num(x & ((1 << 15) - 1), x >> 15); 164 | } 165 | fill(fa.begin() + a.size(), fa.begin() + sz, num {0, 0}); 166 | fft(fa, sz); 167 | if (sz > (int) fb.size()) { 168 | fb.resize(sz); 169 | } 170 | if (eq) { 171 | copy(fa.begin(), fa.begin() + sz, fb.begin()); 172 | } else { 173 | for (int i = 0; i < (int) b.size(); i++) { 174 | int x = (b[i] % m + m) % m; 175 | fb[i] = num(x & ((1 << 15) - 1), x >> 15); 176 | } 177 | fill(fb.begin() + b.size(), fb.begin() + sz, num {0, 0}); 178 | fft(fb, sz); 179 | } 180 | dbl ratio = 0.25 / sz; 181 | num r2(0, -1); 182 | num r3(ratio, 0); 183 | num r4(0, -ratio); 184 | num r5(0, 1); 185 | for (int i = 0; i <= (sz >> 1); i++) { 186 | int j = (sz - i) & (sz - 1); 187 | num a1 = (fa[i] + conj(fa[j])); 188 | num a2 = (fa[i] - conj(fa[j])) * r2; 189 | num b1 = (fb[i] + conj(fb[j])) * r3; 190 | num b2 = (fb[i] - conj(fb[j])) * r4; 191 | if (i != j) { 192 | num c1 = (fa[j] + conj(fa[i])); 193 | num c2 = (fa[j] - conj(fa[i])) * r2; 194 | num d1 = (fb[j] + conj(fb[i])) * r3; 195 | num d2 = (fb[j] - conj(fb[i])) * r4; 196 | fa[i] = c1 * d1 + c2 * d2 * r5; 197 | fb[i] = c1 * d2 + c2 * d1; 198 | } 199 | fa[j] = a1 * b1 + a2 * b2 * r5; 200 | fb[j] = a1 * b2 + a2 * b1; 201 | } 202 | fft(fa, sz); 203 | fft(fb, sz); 204 | vector<int> res(need); 205 | for (int i = 0; i < need; i++) { 206 | int64_t aa = llround(fa[i].x); 207 | int64_t bb = llround(fb[i].x); 208 | int64_t cc = llround(fa[i].y); 209 | res[i] = static_cast<int>((aa + ((bb % m) << 15) + ((cc % m) << 30)) % m); 210 | } 211 | return res; 212 | } 213 | 214 | } // namespace fft 215 | 216 | template <typename T> 217 | typename enable_if<is_same<typename Modular<T>::Type, int>::value, vector<Modular<T>>>::type operator*( 218 | const vector<Modular<T>>& a, 219 | const vector<Modular<T>>& b) { 220 | if (a.empty() || b.empty()) { 221 | return {}; 222 | } 223 | if (min(a.size(), b.size()) < 150) { 224 | vector<Modular<T>> c(a.size() + b.size() - 1, 0); 225 | for (int i = 0; i < (int) a.size(); i++) { 226 | for (int j = 0; j < (int) b.size(); j++) { 227 | c[i + j] += a[i] * b[j]; 228 | } 229 | } 230 | return c; 231 | } 232 | vector<int> a_mul(a.size()); 233 | for (int i = 0; i < (int) a.size(); i++) { 234 | a_mul[i] = static_cast<int>(a[i]); 235 | } 236 | vector<int> b_mul(b.size()); 237 | for (int i = 0; i < (int) b.size(); i++) { 238 | b_mul[i] = static_cast<int>(b[i]); 239 | } 240 | vector<int> c_mul = fft::multiply_mod(a_mul, b_mul, T::value); 241 | vector<Modular<T>> c(c_mul.size()); 242 | for (int i = 0; i < (int) c.size(); i++) { 243 | c[i] = c_mul[i]; 244 | } 245 | return c; 246 | } 247 | 248 | template <typename T> 249 | typename enable_if<is_same<typename Modular<T>::Type, int>::value, vector<Modular<T>>>::type& operator*=( 250 | vector<Modular<T>>& a, 251 | const vector<Modular<T>>& b) { 252 | return a = a * b; 253 | } -------------------------------------------------------------------------------- /numeric/fwht.cpp: -------------------------------------------------------------------------------- 1 | namespace fwht { 2 | 3 | template<typename T> 4 | void hadamard(vector<T> &a) { 5 | int n = a.size(); 6 | for (int k = 1; k < n; k <<= 1) { 7 | for (int i = 0; i < n; i += 2 * k) { 8 | for (int j = 0; j < k; j++) { 9 | T x = a[i + j]; 10 | T y = a[i + j + k]; 11 | a[i + j] = x + y; 12 | a[i + j + k] = x - y; 13 | } 14 | } 15 | } 16 | } 17 | 18 | template<typename T> 19 | vector<T> multiply(vector<T> a, vector<T> b) { 20 | int eq = (a == b); 21 | int n = 1; 22 | while (n < (int) max(a.size(), b.size())) { 23 | n <<= 1; 24 | } 25 | a.resize(n); 26 | b.resize(n); 27 | hadamard(a); 28 | if (eq) b = a; else hadamard(b); 29 | for (int i = 0; i < n; i++) { 30 | a[i] *= b[i]; 31 | } 32 | hadamard(a); 33 | T q = 1 / static_cast<T>(n); 34 | for (int i = 0; i < n; i++) { 35 | a[i] *= q; 36 | } 37 | return a; 38 | } 39 | 40 | } // namespace fwht -------------------------------------------------------------------------------- /numeric/md.cpp: -------------------------------------------------------------------------------- 1 | const int md = @@HERE@@; 2 | 3 | inline void add(int &a, int b) { 4 | a += b; 5 | if (a >= md) a -= md; 6 | } 7 | 8 | inline void sub(int &a, int b) { 9 | a -= b; 10 | if (a < 0) a += md; 11 | } 12 | 13 | inline int mul(int a, int b) { 14 | return (int) ((long long) a * b % md); 15 | } 16 | 17 | inline int power(int a, long long b) { 18 | int res = 1; 19 | while (b > 0) { 20 | if (b & 1) { 21 | res = mul(res, a); 22 | } 23 | a = mul(a, a); 24 | b >>= 1; 25 | } 26 | return res; 27 | } 28 | 29 | inline int inv(int a) { 30 | a %= md; 31 | if (a < 0) a += md; 32 | int b = md, u = 0, v = 1; 33 | while (a) { 34 | int t = b / a; 35 | b -= t * a; swap(a, b); 36 | u -= t * v; swap(u, v); 37 | } 38 | assert(b == 1); 39 | if (u < 0) u += md; 40 | return u; 41 | } -------------------------------------------------------------------------------- /numeric/mint.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | T inverse(T a, T m) { 3 | T u = 0, v = 1; 4 | while (a != 0) { 5 | T t = m / a; 6 | m -= t * a; swap(a, m); 7 | u -= t * v; swap(u, v); 8 | } 9 | assert(m == 1); 10 | return u; 11 | } 12 | 13 | template <typename T> 14 | class Modular { 15 | public: 16 | using Type = typename decay<decltype(T::value)>::type; 17 | 18 | constexpr Modular() : value() {} 19 | template <typename U> 20 | Modular(const U& x) { 21 | value = normalize(x); 22 | } 23 | 24 | template <typename U> 25 | static Type normalize(const U& x) { 26 | Type v; 27 | if (-mod() <= x && x < mod()) v = static_cast<Type>(x); 28 | else v = static_cast<Type>(x % mod()); 29 | if (v < 0) v += mod(); 30 | return v; 31 | } 32 | 33 | const Type& operator()() const { return value; } 34 | template <typename U> 35 | explicit operator U() const { return static_cast<U>(value); } 36 | constexpr static Type mod() { return T::value; } 37 | 38 | Modular& operator+=(const Modular& other) { if ((value += other.value) >= mod()) value -= mod(); return *this; } 39 | Modular& operator-=(const Modular& other) { if ((value -= other.value) < 0) value += mod(); return *this; } 40 | template <typename U> Modular& operator+=(const U& other) { return *this += Modular(other); } 41 | template <typename U> Modular& operator-=(const U& other) { return *this -= Modular(other); } 42 | Modular& operator++() { return *this += 1; } 43 | Modular& operator--() { return *this -= 1; } 44 | Modular operator++(int) { Modular result(*this); *this += 1; return result; } 45 | Modular operator--(int) { Modular result(*this); *this -= 1; return result; } 46 | Modular operator-() const { return Modular(-value); } 47 | 48 | template <typename U = T> 49 | typename enable_if<is_same<typename Modular<U>::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) { 50 | #ifdef _WIN32 51 | uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value); 52 | uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x), d, m; 53 | asm( 54 | "divl %4; \n\t" 55 | : "=a" (d), "=d" (m) 56 | : "d" (xh), "a" (xl), "r" (mod()) 57 | ); 58 | value = m; 59 | #else 60 | value = normalize(static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value)); 61 | #endif 62 | return *this; 63 | } 64 | template <typename U = T> 65 | typename enable_if<is_same<typename Modular<U>::Type, int64_t>::value, Modular>::type& operator*=(const Modular& rhs) { 66 | int64_t q = static_cast<int64_t>(static_cast<long double>(value) * rhs.value / mod()); 67 | value = normalize(value * rhs.value - q * mod()); 68 | return *this; 69 | } 70 | template <typename U = T> 71 | typename enable_if<!is_integral<typename Modular<U>::Type>::value, Modular>::type& operator*=(const Modular& rhs) { 72 | value = normalize(value * rhs.value); 73 | return *this; 74 | } 75 | 76 | Modular& operator/=(const Modular& other) { return *this *= Modular(inverse(other.value, mod())); } 77 | 78 | template <typename U> 79 | friend bool operator==(const Modular<U>& lhs, const Modular<U>& rhs); 80 | 81 | template <typename U> 82 | friend bool operator<(const Modular<U>& lhs, const Modular<U>& rhs); 83 | 84 | template <typename U> 85 | friend std::istream& operator>>(std::istream& stream, Modular<U>& number); 86 | 87 | private: 88 | Type value; 89 | }; 90 | 91 | template <typename T> bool operator==(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value == rhs.value; } 92 | template <typename T, typename U> bool operator==(const Modular<T>& lhs, U rhs) { return lhs == Modular<T>(rhs); } 93 | template <typename T, typename U> bool operator==(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) == rhs; } 94 | 95 | template <typename T> bool operator!=(const Modular<T>& lhs, const Modular<T>& rhs) { return !(lhs == rhs); } 96 | template <typename T, typename U> bool operator!=(const Modular<T>& lhs, U rhs) { return !(lhs == rhs); } 97 | template <typename T, typename U> bool operator!=(U lhs, const Modular<T>& rhs) { return !(lhs == rhs); } 98 | 99 | template <typename T> bool operator<(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value < rhs.value; } 100 | 101 | template <typename T> Modular<T> operator+(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; } 102 | template <typename T, typename U> Modular<T> operator+(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) += rhs; } 103 | template <typename T, typename U> Modular<T> operator+(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; } 104 | 105 | template <typename T> Modular<T> operator-(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; } 106 | template <typename T, typename U> Modular<T> operator-(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) -= rhs; } 107 | template <typename T, typename U> Modular<T> operator-(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; } 108 | 109 | template <typename T> Modular<T> operator*(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; } 110 | template <typename T, typename U> Modular<T> operator*(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) *= rhs; } 111 | template <typename T, typename U> Modular<T> operator*(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; } 112 | 113 | template <typename T> Modular<T> operator/(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; } 114 | template <typename T, typename U> Modular<T> operator/(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) /= rhs; } 115 | template <typename T, typename U> Modular<T> operator/(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; } 116 | 117 | template<typename T, typename U> 118 | Modular<T> power(const Modular<T>& a, const U& b) { 119 | assert(b >= 0); 120 | Modular<T> x = a, res = 1; 121 | U p = b; 122 | while (p > 0) { 123 | if (p & 1) res *= x; 124 | x *= x; 125 | p >>= 1; 126 | } 127 | return res; 128 | } 129 | 130 | template <typename T> 131 | string to_string(const Modular<T>& number) { 132 | return to_string(number()); 133 | } 134 | 135 | template <typename T> 136 | std::ostream& operator<<(std::ostream& stream, const Modular<T>& number) { 137 | return stream << number(); 138 | } 139 | 140 | template <typename T> 141 | std::istream& operator>>(std::istream& stream, Modular<T>& number) { 142 | typename common_type<typename Modular<T>::Type, int64_t>::type x; 143 | stream >> x; 144 | number.value = Modular<T>::normalize(x); 145 | return stream; 146 | } 147 | 148 | /* 149 | using ModType = int; 150 | 151 | struct VarMod { static ModType value; }; 152 | ModType VarMod::value; 153 | ModType& md = VarMod::value; 154 | using Mint = Modular<VarMod>; 155 | */ 156 | 157 | constexpr int md = @@HERE@@; 158 | using Mint = Modular<std::integral_constant<decay<decltype(md)>::type, md>>; -------------------------------------------------------------------------------- /numeric/ntt.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | class NTT { 3 | public: 4 | using Type = typename decay<decltype(T::value)>::type; 5 | 6 | static Type md; 7 | static Modular<T> root; 8 | static int base; 9 | static int max_base; 10 | static vector<Modular<T>> roots; 11 | static vector<int> rev; 12 | 13 | static void clear() { 14 | root = 0; 15 | base = 0; 16 | max_base = 0; 17 | roots.clear(); 18 | rev.clear(); 19 | } 20 | 21 | static void init() { 22 | md = T::value; 23 | assert(md >= 3 && md % 2 == 1); 24 | auto tmp = md - 1; 25 | max_base = 0; 26 | while (tmp % 2 == 0) { 27 | tmp /= 2; 28 | max_base++; 29 | } 30 | root = 2; 31 | while (power(root, (md - 1) >> 1) == 1) { 32 | root++; 33 | } 34 | assert(power(root, md - 1) == 1); 35 | root = power(root, (md - 1) >> max_base); 36 | base = 1; 37 | rev = {0, 1}; 38 | roots = {0, 1}; 39 | } 40 | 41 | static void ensure_base(int nbase) { 42 | if (md != T::value) { 43 | clear(); 44 | } 45 | if (roots.empty()) { 46 | init(); 47 | } 48 | if (nbase <= base) { 49 | return; 50 | } 51 | assert(nbase <= max_base); 52 | rev.resize(1 << nbase); 53 | for (int i = 0; i < (1 << nbase); i++) { 54 | rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1)); 55 | } 56 | roots.resize(1 << nbase); 57 | while (base < nbase) { 58 | Modular<T> z = power(root, 1 << (max_base - 1 - base)); 59 | for (int i = 1 << (base - 1); i < (1 << base); i++) { 60 | roots[i << 1] = roots[i]; 61 | roots[(i << 1) + 1] = roots[i] * z; 62 | } 63 | base++; 64 | } 65 | } 66 | 67 | static void fft(vector<Modular<T>> &a) { 68 | int n = (int) a.size(); 69 | assert((n & (n - 1)) == 0); 70 | int zeros = __builtin_ctz(n); 71 | ensure_base(zeros); 72 | int shift = base - zeros; 73 | for (int i = 0; i < n; i++) { 74 | if (i < (rev[i] >> shift)) { 75 | swap(a[i], a[rev[i] >> shift]); 76 | } 77 | } 78 | for (int k = 1; k < n; k <<= 1) { 79 | for (int i = 0; i < n; i += 2 * k) { 80 | for (int j = 0; j < k; j++) { 81 | Modular<T> x = a[i + j]; 82 | Modular<T> y = a[i + j + k] * roots[j + k]; 83 | a[i + j] = x + y; 84 | a[i + j + k] = x - y; 85 | } 86 | } 87 | } 88 | } 89 | 90 | static vector<Modular<T>> multiply(vector<Modular<T>> a, vector<Modular<T>> b) { 91 | if (a.empty() || b.empty()) { 92 | return {}; 93 | } 94 | int eq = (a == b); 95 | int need = (int) a.size() + (int) b.size() - 1; 96 | int nbase = 0; 97 | while ((1 << nbase) < need) nbase++; 98 | ensure_base(nbase); 99 | int sz = 1 << nbase; 100 | a.resize(sz); 101 | b.resize(sz); 102 | fft(a); 103 | if (eq) b = a; else fft(b); 104 | Modular<T> inv_sz = 1 / static_cast<Modular<T>>(sz); 105 | for (int i = 0; i < sz; i++) { 106 | a[i] *= b[i] * inv_sz; 107 | } 108 | reverse(a.begin() + 1, a.end()); 109 | fft(a); 110 | a.resize(need); 111 | return a; 112 | } 113 | }; 114 | 115 | template <typename T> typename NTT<T>::Type NTT<T>::md; 116 | template <typename T> Modular<T> NTT<T>::root; 117 | template <typename T> int NTT<T>::base; 118 | template <typename T> int NTT<T>::max_base; 119 | template <typename T> vector<Modular<T>> NTT<T>::roots; 120 | template <typename T> vector<int> NTT<T>::rev; 121 | 122 | template <typename T> 123 | vector<Modular<T>> inverse(const vector<Modular<T>>& a) { 124 | assert(!a.empty()); 125 | int n = (int) a.size(); 126 | vector<Modular<T>> b = {1 / a[0]}; 127 | while ((int) b.size() < n) { 128 | vector<Modular<T>> x(a.begin(), a.begin() + min(a.size(), b.size() << 1)); 129 | x.resize(b.size() << 1); 130 | b.resize(b.size() << 1); 131 | vector<Modular<T>> c = b; 132 | NTT<T>::fft(c); 133 | NTT<T>::fft(x); 134 | Modular<T> inv = 1 / static_cast<Modular<T>>((int) x.size()); 135 | for (int i = 0; i < (int) x.size(); i++) { 136 | x[i] *= c[i] * inv; 137 | } 138 | reverse(x.begin() + 1, x.end()); 139 | NTT<T>::fft(x); 140 | rotate(x.begin(), x.begin() + (x.size() >> 1), x.end()); 141 | fill(x.begin() + (x.size() >> 1), x.end(), 0); 142 | NTT<T>::fft(x); 143 | for (int i = 0; i < (int) x.size(); i++) { 144 | x[i] *= c[i] * inv; 145 | } 146 | reverse(x.begin() + 1, x.end()); 147 | NTT<T>::fft(x); 148 | for (int i = 0; i < ((int) x.size() >> 1); i++) { 149 | b[i + ((int) x.size() >> 1)] = -x[i]; 150 | } 151 | } 152 | b.resize(n); 153 | return b; 154 | } 155 | 156 | template <typename T> 157 | vector<Modular<T>> inverse_old(vector<Modular<T>> a) { 158 | assert(!a.empty()); 159 | int n = (int) a.size(); 160 | if (n == 1) { 161 | return {1 / a[0]}; 162 | } 163 | int m = (n + 1) >> 1; 164 | vector<Modular<T>> b = inverse(vector<Modular<T>>(a.begin(), a.begin() + m)); 165 | int need = n << 1; 166 | int nbase = 0; 167 | while ((1 << nbase) < need) { 168 | ++nbase; 169 | } 170 | NTT<T>::ensure_base(nbase); 171 | int size = 1 << nbase; 172 | a.resize(size); 173 | b.resize(size); 174 | NTT<T>::fft(a); 175 | NTT<T>::fft(b); 176 | Modular<T> inv = 1 / static_cast<Modular<T>>(size); 177 | for (int i = 0; i < size; ++i) { 178 | a[i] = (2 - a[i] * b[i]) * b[i] * inv; 179 | } 180 | reverse(a.begin() + 1, a.end()); 181 | NTT<T>::fft(a); 182 | a.resize(n); 183 | return a; 184 | } 185 | 186 | template <typename T> 187 | vector<Modular<T>> operator*(const vector<Modular<T>>& a, const vector<Modular<T>>& b) { 188 | if (a.empty() || b.empty()) { 189 | return {}; 190 | } 191 | if (min(a.size(), b.size()) < 150) { 192 | vector<Modular<T>> c(a.size() + b.size() - 1, 0); 193 | for (int i = 0; i < (int) a.size(); i++) { 194 | for (int j = 0; j < (int) b.size(); j++) { 195 | c[i + j] += a[i] * b[j]; 196 | } 197 | } 198 | return c; 199 | } 200 | return NTT<T>::multiply(a, b); 201 | } 202 | 203 | template <typename T> 204 | vector<Modular<T>>& operator*=(vector<Modular<T>>& a, const vector<Modular<T>>& b) { 205 | return a = a * b; 206 | } -------------------------------------------------------------------------------- /numeric/primitive.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | struct PrimitiveVarMod { static T value; }; 3 | template <typename T> 4 | T PrimitiveVarMod<T>::value; 5 | 6 | template <typename T, class F> 7 | T GetPrimitiveRoot(const T& modulo, const F& factorize) { 8 | if (modulo <= 0) { 9 | return -1; 10 | } 11 | if (modulo == 1 || modulo == 2 || modulo == 4) { 12 | return modulo - 1; 13 | } 14 | vector<pair<T, int>> modulo_factors = factorize(modulo); 15 | if (modulo_factors[0].first == 2 && (modulo_factors[0].second != 1 || modulo_factors.size() != 2)) { 16 | return -1; 17 | } 18 | if (modulo_factors[0].first != 2 && modulo_factors.size() != 1) { 19 | return -1; 20 | } 21 | set<T> phi_factors; 22 | T phi = modulo; 23 | for (auto& d : modulo_factors) { 24 | phi = phi / d.first * (d.first - 1); 25 | if (d.second > 1) { 26 | phi_factors.insert(d.first); 27 | } 28 | for (auto& e : factorize(d.first - 1)) { 29 | phi_factors.insert(e.first); 30 | } 31 | } 32 | PrimitiveVarMod<T>::value = modulo; 33 | Modular<PrimitiveVarMod<T>> gen = 2; 34 | while (gen != 0) { 35 | if (power(gen, phi) != 1) { 36 | continue; 37 | } 38 | bool ok = true; 39 | for (auto& p : phi_factors) { 40 | if (power(gen, phi / p) == 1) { 41 | ok = false; 42 | break; 43 | } 44 | } 45 | if (ok) { 46 | return gen(); 47 | } 48 | gen++; 49 | } 50 | assert(false); 51 | return -1; 52 | } 53 | 54 | template <typename T> 55 | T GetPrimitiveRoot(const T& modulo) { 56 | return GetPrimitiveRoot(modulo, factorizer::Factorize<T>); 57 | } -------------------------------------------------------------------------------- /string/duval.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | int duval(int n, const T &s) { 3 | assert(n >= 1); 4 | int i = 0, ans = 0; 5 | while (i < n) { 6 | ans = i; 7 | int j = i + 1, k = i; 8 | while (j < n + n && !(s[j % n] < s[k % n])) { 9 | if (s[k % n] < s[j % n]) { 10 | k = i; 11 | } else { 12 | k++; 13 | } 14 | j++; 15 | } 16 | while (i <= k) { 17 | i += j - k; 18 | } 19 | } 20 | return ans; 21 | // returns 0-indexed position of the least cyclic shift 22 | } 23 | 24 | template <typename T> 25 | int duval(const T &s) { 26 | return duval((int) s.size(), s); 27 | } -------------------------------------------------------------------------------- /string/duval_prefixes.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> duval_prefixes(int n, const T &s) { 3 | vector<int> z = z_function(n, s); 4 | vector<int> ans(n, 0); 5 | int i = 0, pos = 0; 6 | while (i < n) { 7 | int j = i, k = i; 8 | while (j < n) { 9 | j++; 10 | if (j > pos) { 11 | if (z[k] <= pos - k && s[z[k]] < s[k + z[k]]) { 12 | int shift = (pos - i) / (j - k) * (j - k); 13 | ans[pos] = ans[pos - shift] + shift; 14 | } else { 15 | ans[pos] = i; 16 | } 17 | pos++; 18 | } 19 | if (s[k] < s[j]) k = i; else 20 | if (!(s[j] < s[k])) k++; else 21 | else break; 22 | } 23 | while (i <= k) { 24 | i += j - k; 25 | } 26 | } 27 | return ans; 28 | // returns 0-indexed positions of the least cyclic shifts of all prefixes 29 | } 30 | 31 | template <typename T> 32 | vector<int> duval_prefixes(const T &s) { 33 | return duval_prefixes((int) s.size(), s); 34 | } -------------------------------------------------------------------------------- /string/kmp.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> kmp_table(int n, const T &s) { 3 | vector<int> p(n, 0); 4 | int k = 0; 5 | for (int i = 1; i < n; i++) { 6 | while (k > 0 && !(s[i] == s[k])) { 7 | k = p[k - 1]; 8 | } 9 | if (s[i] == s[k]) { 10 | k++; 11 | } 12 | p[i] = k; 13 | } 14 | return p; 15 | } 16 | 17 | template <typename T> 18 | vector<int> kmp_table(const T &s) { 19 | return kmp_table((int) s.size(), s); 20 | } 21 | 22 | template <typename T> 23 | vector<int> kmp_search(int n, const T &s, int m, const T &w, const vector<int> &p) { 24 | assert(n >= 1 && (int) p.size() == n); 25 | vector<int> res; 26 | int k = 0; 27 | for (int i = 0; i < m; i++) { 28 | while (k > 0 && (k == n || !(w[i] == s[k]))) { 29 | k = p[k - 1]; 30 | } 31 | if (w[i] == s[k]) { 32 | k++; 33 | } 34 | if (k == n) { 35 | res.push_back(i - n + 1); 36 | } 37 | } 38 | return res; 39 | // returns 0-indexed positions of occurrences of w in s 40 | } 41 | 42 | template <typename T> 43 | vector<int> kmp_search(const T &s, const T &w, const vector<int> &p) { 44 | return kmp_search((int) s.size(), s, (int) w.size(), w, p); 45 | } -------------------------------------------------------------------------------- /string/manacher.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> manacher(int n, const T &s) { 3 | if (n == 0) { 4 | return vector<int>(); 5 | } 6 | vector<int> res(2 * n - 1, 0); 7 | int l = -1, r = -1; 8 | for (int z = 0; z < 2 * n - 1; z++) { 9 | int i = (z + 1) >> 1; 10 | int j = z >> 1; 11 | int p = (i >= r ? 0 : min(r - i, res[2 * (l + r) - z])); 12 | while (j + p + 1 < n && i - p - 1 >= 0) { 13 | if (!(s[j + p + 1] == s[i - p - 1])) { 14 | break; 15 | } 16 | p++; 17 | } 18 | if (j + p > r) { 19 | l = i - p; 20 | r = j + p; 21 | } 22 | res[z] = p; 23 | } 24 | return res; 25 | // res[2 * i] = odd radius in position i 26 | // res[2 * i + 1] = even radius between positions i and i + 1 27 | // s = "abaa" -> res = {0, 0, 1, 0, 0, 1, 0} 28 | // in other words, for every z from 0 to 2 * n - 2: 29 | // calculate i = (z + 1) >> 1 and j = z >> 1 30 | // now there is a palindrome from i - res[z] to j + res[z] 31 | // (watch out for i > j and res[z] = 0) 32 | } 33 | 34 | template <typename T> 35 | vector<int> manacher(const T &s) { 36 | return manacher((int) s.size(), s); 37 | } -------------------------------------------------------------------------------- /string/suffix_array.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> suffix_array(int n, const T &s, int char_bound) { 3 | vector<int> a(n); 4 | if (n == 0) { 5 | return a; 6 | } 7 | if (char_bound != -1) { 8 | vector<int> aux(char_bound, 0); 9 | for (int i = 0; i < n; i++) { 10 | aux[s[i]]++; 11 | } 12 | int sum = 0; 13 | for (int i = 0; i < char_bound; i++) { 14 | int add = aux[i]; 15 | aux[i] = sum; 16 | sum += add; 17 | } 18 | for (int i = 0; i < n; i++) { 19 | a[aux[s[i]]++] = i; 20 | } 21 | } else { 22 | iota(a.begin(), a.end(), 0); 23 | sort(a.begin(), a.end(), [&s](int i, int j) { return s[i] < s[j]; }); 24 | } 25 | vector<int> sorted_by_second(n); 26 | vector<int> ptr_group(n); 27 | vector<int> new_group(n); 28 | vector<int> group(n); 29 | group[a[0]] = 0; 30 | for (int i = 1; i < n; i++) { 31 | group[a[i]] = group[a[i - 1]] + (!(s[a[i]] == s[a[i - 1]])); 32 | } 33 | int cnt = group[a[n - 1]] + 1; 34 | int step = 1; 35 | while (cnt < n) { 36 | int at = 0; 37 | for (int i = n - step; i < n; i++) { 38 | sorted_by_second[at++] = i; 39 | } 40 | for (int i = 0; i < n; i++) { 41 | if (a[i] - step >= 0) { 42 | sorted_by_second[at++] = a[i] - step; 43 | } 44 | } 45 | for (int i = n - 1; i >= 0; i--) { 46 | ptr_group[group[a[i]]] = i; 47 | } 48 | for (int i = 0; i < n; i++) { 49 | int x = sorted_by_second[i]; 50 | a[ptr_group[group[x]]++] = x; 51 | } 52 | new_group[a[0]] = 0; 53 | for (int i = 1; i < n; i++) { 54 | if (group[a[i]] != group[a[i - 1]]) { 55 | new_group[a[i]] = new_group[a[i - 1]] + 1; 56 | } else { 57 | int pre = (a[i - 1] + step >= n ? -1 : group[a[i - 1] + step]); 58 | int cur = (a[i] + step >= n ? -1 : group[a[i] + step]); 59 | new_group[a[i]] = new_group[a[i - 1]] + (pre != cur); 60 | } 61 | } 62 | swap(group, new_group); 63 | cnt = group[a[n - 1]] + 1; 64 | step <<= 1; 65 | } 66 | return a; 67 | } 68 | 69 | template <typename T> 70 | vector<int> suffix_array(const T &s, int char_bound) { 71 | return suffix_array((int) s.size(), s, char_bound); 72 | } 73 | 74 | template <typename T> 75 | vector<int> build_lcp(int n, const T &s, const vector<int> &sa) { 76 | assert((int) sa.size() == n); 77 | vector<int> pos(n); 78 | for (int i = 0; i < n; i++) { 79 | pos[sa[i]] = i; 80 | } 81 | vector<int> lcp(max(n - 1, 0)); 82 | int k = 0; 83 | for (int i = 0; i < n; i++) { 84 | k = max(k - 1, 0); 85 | if (pos[i] == n - 1) { 86 | k = 0; 87 | } else { 88 | int j = sa[pos[i] + 1]; 89 | while (i + k < n && j + k < n && s[i + k] == s[j + k]) { 90 | k++; 91 | } 92 | lcp[pos[i]] = k; 93 | } 94 | } 95 | return lcp; 96 | } 97 | 98 | template <typename T> 99 | vector<int> build_lcp(const T &s, const vector<int> &sa) { 100 | return build_lcp((int) s.size(), s, sa); 101 | } -------------------------------------------------------------------------------- /string/z.cpp: -------------------------------------------------------------------------------- 1 | template <typename T> 2 | vector<int> z_function(int n, const T &s) { 3 | vector<int> z(n, n); 4 | int l = 0, r = 0; 5 | for (int i = 1; i < n; i++) { 6 | z[i] = (i > r ? 0 : min(r - i + 1, z[i - l])); 7 | while (i + z[i] < n && s[z[i]] == s[i + z[i]]) { 8 | z[i]++; 9 | } 10 | if (i + z[i] - 1 > r) { 11 | l = i; 12 | r = i + z[i] - 1; 13 | } 14 | } 15 | return z; 16 | } 17 | 18 | template <typename T> 19 | vector<int> z_function(const T &s) { 20 | return z_function((int) s.size(), s); 21 | } -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | 0) FIX MAX FLOW? https://official.contest.yandex.ru/moscodefest2018/contest/7923/enter/ moscode2018-ind125 9KJs2z4YGS 2 | (also ya.algo 2018 r3 E, check niyaz's solution in T.) 3 | 4 | + 1) bridges 5 | + 2) cutpoints 6 | + 3) bicone 7 | + 4) biconv 8 | + 5) dfs 9 | 6) chinese algo 10 | + 7) lca 11 | + 8) hld (test hld on CF Round 434 E) 12 | + 9) mcmf 13 | + 10) maximum matching 14 | + 11) hungarian algorithm 15 | 12) point2d 16 | 13) mindisc 17 | 14) convex hull (+dynamic) (+for lines) (csacademy round ~70?) 18 | 15) semiplane intersection 19 | 16) point3d 20 | 17) convex hull 3d 21 | 18) aho-corasick 22 | + 19) suffix array 23 | + 20) duval 24 | + 21) duval-prefixes 25 | 22) suffix automaton 26 | + 23) kmp 27 | + 24) z 28 | 25) suffix tree (presumably from suffix automaton) 29 | + 26) multiply long longs modulo long long 30 | 27) simplex method 31 | + 28) extended euclid 32 | + 29) CRT 33 | 30) discrete logarithm 34 | 31) discrete root 35 | 32) matrix determinant 36 | 33) gaussian elimination in general 37 | + 34) segment tree 38 | 35) treap 39 | 36) bigint 40 | 37) wavelet trees 41 | 38) polynomial interpolation 42 | 39) polynomial division (memsql cup 3.0 r2 G) 43 | 40) inverse polynomial 44 | + 41) flow decomposition 45 | 42) eertree 46 | + 43) manacher 47 | + 44) 2-sat 48 | 45) matrix multiplication (test on opencup 17/18 baltic E) 49 | 46) matrix exponentiation 50 | 47) dynamic connectivity offline 51 | 48) link-cut 52 | 49) dynamic connectivity online 53 | + 50) eprintf 54 | + 51) pollard rho 55 | 52) CRT garner 56 | + 53) primitive root 57 | + 54) miller-rabin test 58 | 55) global min-cut 59 | + 56) gomory-hu tree 60 | 57) some kind of sqrt-decomposition 61 | 58) fix bugs in plugin :( [sometimes prints trash at the end] 62 | 59) linear sieve 63 | 60) persistent segment tree 64 | + 61) fast flow (preflow push?) 65 | 62) fast input 66 | 63) fast output 67 | 64) dynamic segment tree 68 | 65) ji driver segment tree 69 | 66) sparse table (http://codeforces.com/contest/875/submission/31414300) 70 | 67) template for old gcj/hackercup (multithreaded) 71 | 68) li chao segment tree 72 | 69) berlekamp-massey (test on ITMO 2018 winter ptz contest F) (http://codeforces.com/contest/963/problem/E) 73 | 70) multipoint evaluation (http://people.csail.mit.edu/madhu/ST12/scribe/lect06.pdf) 74 | + 71) euler tour 75 | 72) some kind of ford-bellman 76 | 73) edmonds blossom 77 | 74) learn about dual problems 78 | 75) weighted general matching (http://codeforces.com/blog/entry/49402) 79 | 76) centroid decomposition (http://codeforces.com/contest/757/problem/G) 80 | 77) minimum vertex cover/maximum independent set (bipartite) 81 | 78) dfa/nfa/regex... (check on opencup siberia/eurasia 2017-2018 problem) 82 | 79) squfof 83 | 80) bfs? (should be faster than dfs) 84 | 81) radix sort? (http://codeforces.com/contest/940/submission/35636024) 85 | 82) pragmas 86 | 83) matroid intersection of some kind 87 | 84) tonelli-shanks and their friends (opencup 17/18 baltic G) 88 | 85) schreier-sims algorithm 89 | 86) link-cut memphis? 90 | 87) operations on formal power series (http://codeforces.com/blog/entry/56422, http://codeforces.com/contest/865/problem/G) 91 | 88) compare fft to http://codeforces.com/contest/958/submission/37318120 92 | 89) induced subtree (test on VK Cup 2018 Round 3 E) 93 | 90) poker hands evaluation (vekua cup 2018) 94 | 91) exponential generating function 95 | 92) voronoi diagram/delaunay triangulation 96 | 93) get rid of __int128 everywhere 97 | 94) does prefix function (z-algorithm) with question marks work? 98 | 95) acm icpc world finals 2018 problem C (check discussion with vartem in T.) 99 | 96) perfect order elimination (https://www.codechef.com/JULY18A/problems/JERRYTOM) 100 | 97) faulhaber's formula via bernoulli numbers (https://www.codechef.com/JULY18A/problems/PFRUIT) 101 | 98) rectilinear MST (CSA Round 84) 102 | 103 | probably not to do, but still fun: 104 | 1) quadratic sieve 105 | --------------------------------------------------------------------------------