├── LICENSE ├── Notebooks Compilados ├── c++ │ ├── Notebook C++.tex │ └── cpp.pdf └── java │ ├── Notebook Java.tex │ └── java.pdf ├── README.md ├── c++ ├── Data structures │ ├── Centroid Decomposition.cpp │ ├── Convex Hull Trick.cpp │ ├── Disjoint Set.cpp │ ├── Dsu on Tree (Sack).cpp │ ├── Fenwick Tree.cpp │ ├── Heavy Light Decomposition.cpp │ ├── Min queue.cpp │ ├── Ordered Set.cpp │ ├── Persistent Segment Tree.cpp │ ├── Segment Tree (Lazy Propagation).cpp │ ├── Segment Tree 2D.cpp │ ├── Sparse Table.cpp │ └── Sparse table 2D.cpp ├── Dynamic programming │ ├── Longest Increasing Subsequence.cpp │ ├── Max Range Sum.cpp │ ├── Min Max Range.cpp │ └── Traveling Salesman Problem.cpp ├── Geometry │ ├── Point.cpp │ ├── circle.cpp │ ├── halfplanes.cpp │ ├── line.cpp │ ├── polygon.cpp │ └── segment.cpp ├── Graphs │ ├── 2-satisfiability.cpp │ ├── Articulation Bridges Biconnected.cpp │ ├── BFS.cpp │ ├── Bellman Ford.cpp │ ├── Bipartite Check.cpp │ ├── Cycle Detection.cpp │ ├── DFS.cpp │ ├── Dijkstra.cpp │ ├── Flood Fill.cpp │ ├── Floyd Warshall.cpp │ ├── Kruskal.cpp │ ├── Lowest Common Ancestor.cpp │ ├── Prim.cpp │ ├── Tarjan.cpp │ ├── Topological Sort.cpp │ └── Tree Isomorphism.cpp ├── Math │ ├── Basis of a Vector Space (mod 2 Field).cpp │ ├── Binomial Coefficient.cpp │ ├── Diophantine Ecuations.cpp │ ├── Divisors.cpp │ ├── Euler Totient.cpp │ ├── Extended Euclides.cpp │ ├── Fast Fourier Transform.cpp │ ├── Fraction.cpp │ ├── Gauss Jordan.cpp │ ├── Greatest Common Divisor.cpp │ ├── Lowest Common Multiple.cpp │ ├── Miller Rabin.cpp │ ├── Mobius.cpp │ ├── Pollard Rho.cpp │ ├── Prime Factorization.cpp │ ├── Sieve of Eratosthenes.cpp │ ├── Simplex integer.cpp │ ├── Simplex.cpp │ └── Ternary Search.cpp ├── Modular arithmetic │ ├── Chinese Remainder Theorem.cpp │ ├── Discrete Logarithm.cpp │ ├── Fibonacci mod m.cpp │ ├── Linear Recurrence.cpp │ ├── Matrix Multiplication.cpp │ ├── Modular Exponentiation.cpp │ ├── Modular Inverse.cpp │ ├── Modular Multiplication.cpp │ ├── Pisano Period.cpp │ └── Primitive Root.cpp ├── Network flows │ ├── Blossom.cpp │ ├── Dinic.cpp │ ├── Hungarian.cpp │ ├── Maximum Bipartite Matching.cpp │ ├── MinCost MaxFlow.cpp │ ├── Stoer Wagner.cpp │ └── Weighted matching.cpp ├── Strings │ ├── Aho Corasick (Trie).cpp │ ├── Hashing.cpp │ ├── KMP Automaton.cpp │ ├── KMP.cpp │ ├── Manacher.cpp │ ├── Minimum Expression.cpp │ ├── Palindromic tree.cpp │ ├── Prefix Function.cpp │ ├── Suffix Array.cpp │ ├── Suffix Automaton.cpp │ └── Z Function.cpp ├── Utilities │ ├── Bits Manipulation.cpp │ ├── Random Integer.cpp │ ├── Split String.cpp │ ├── Template.cpp │ └── scanf and printf.cpp └── Values sequences and results │ ├── ASCII Table.tex │ ├── Formulas.tex │ ├── Sequences.tex │ └── Time Complexities.tex ├── java [outdated] ├── Data Structures │ ├── Disjoint Set.java │ ├── Fenwick Tree.java │ ├── RMQ.java │ └── Sparse Table.java ├── Dynamic Programming │ ├── Coin change.java │ ├── Knapsack.java │ ├── Longest Common Subsequence.java │ ├── Longest increasing subsequence.java │ ├── Max Range 2D.java │ ├── Max Range 3D.java │ ├── Max Range Sum.java │ ├── Min Max Range.java │ └── Traveling Salesman Problem.java ├── Geometry │ ├── Angle.java │ ├── Area.java │ ├── Collinear Points.java │ ├── Convex Hull.java │ ├── Euclidean Distance.java │ ├── Gometric Vector.java │ ├── Perimeter.java │ ├── Point in Polygon.java │ ├── Point.java │ └── Sexagesimal degrees and radians.java ├── Graphs │ ├── BFS.java │ ├── Bipartite Check.java │ ├── DFS.java │ ├── Dijkstra.java │ ├── FloodFill.java │ ├── Floyd Warshall.java │ ├── Kruskal.java │ ├── LoopCheck.java │ ├── Lowest Common Ancestor.java │ ├── Maxflow.java │ ├── Prim.java │ ├── Puentes itmos.java │ ├── Tarjan.java │ └── Topological Sort.java ├── Math │ ├── Binomial Coefficient.java │ ├── Catalan Number.java │ ├── Euler Totient.java │ ├── Extended Euclides.java │ ├── Gaussian Elimination.java │ ├── Greatest common divisor.java │ ├── Lowest Common multiple.java │ ├── Miller-Rabin.java │ ├── Mobius.java │ ├── Pollard Rho.java │ ├── Prime Factorization.java │ └── Sieve of Eratosthenes.java ├── Modular arithmetic │ ├── Chinese Remainder Theorem.java │ ├── Fibonacci mod m.java │ ├── Modular Exponentiation.java │ ├── Modular Inverse.java │ ├── Modular Multiplication.java │ └── Pisano Period.java ├── Strings │ ├── KMP's Algorithm.java │ ├── Prefix Function.java │ ├── Prefix-Function.java │ ├── String Hashing.java │ ├── Suffix Array Init.java │ ├── Suffix Array Longest Common Prefix.java │ ├── Suffix Array Longest Common Substring.java │ ├── Suffix Array Longest Repeated Substring.java │ ├── Suffix Array String Matching Boolean.java │ ├── Suffix Array String Matching.java │ ├── Suffix Array strncmp.java │ ├── Trie.java │ └── Z-Function.java ├── Utilities │ ├── Binary search.java │ ├── Biseccion.java │ ├── Bit Manipulation.java │ ├── Lower bound.java │ ├── Optimized Scanner.java │ ├── Template.java │ ├── Ternary Search.java │ └── Upper bound.java └── Values sequences and results │ ├── ASCII Table.tex │ ├── Formulas.tex │ ├── Sequences.tex │ └── Time Complexities.tex └── logonotebook.png /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Grupo de Estudio en Programación Competitiva UFPS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Notebooks Compilados/c++/cpp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgramacionCompetitivaUFPS/notebook/0e08e9435c333c575848408b46738d1f89cdc38f/Notebooks Compilados/c++/cpp.pdf -------------------------------------------------------------------------------- /Notebooks Compilados/java/java.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgramacionCompetitivaUFPS/notebook/0e08e9435c333c575848408b46738d1f89cdc38f/Notebooks Compilados/java/java.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Notebook UFPS - ICPC 2 | 3 | Notebooks oficiales de la Universidad Francisco de Paula Santander en C++ y Java para competencias ICPC. 4 | 5 | Los archivos actuales compilados se encuentran en latex y pdf, en el folder "Notebooks Compilados", mientras que los folders de cada lenguaje contienen los códigos propios del lenguaje. 6 | 7 | Se invita a los estudiantes del semillero a aportar sus propios códigos al notebook, o bien, a indicar temas que consideran deberían ser incluidos mediante issues. 8 | 9 | ### Agradecimientos y créditos: 10 | 11 | - Varios de los algoritmos aquí planteados son implementados/adaptados gracias a los libros y materiales de: 12 | - Antti Laaksonen: [Competitive Programmer's Handbook](https://cses.fi/book/). 13 | - Victor Lecomte: [Handbook Of Geometry For Competitive Programmers](https://vlecomte.github.io/cp-geo.pdf). 14 | - Steven Halim: [Competitive Programming 3](http://cpbook.net/). 15 | - [CP-Algorithms](https://cp-algorithms.com/) (traducción de [MAXimal](http://e-maxx.ru/algo/) a ingles). 16 | - Blogs en [Codeforces](http://codeforces.com/). 17 | - Notebook del equipo "DescomUNAL": [notebook_descomUNAL](https://github.com/ahoraSoyPeor/notebook_descomUNAL). 18 | - Notebook del equipo "UNC - Gracias Demetrio": [icpc-team-notebook-el-vasito](https://github.com/mhunicken/icpc-team-notebook-el-vasito). 19 | - El notebook es generado gracias al [Notebook Generator](https://github.com/pin3da/notebook-generator) de [@pin3da](https://github.com/pin3da/). 20 | -------------------------------------------------------------------------------- /c++/Data structures/Centroid Decomposition.cpp: -------------------------------------------------------------------------------- 1 | > !! Usar build() para inicializar. Problema de ejemplo: dado un árbol, las actualizaciones son marcar nodos, y las consultas son hallar la distancia mínima entre un nodo u y un nodo marcado. 2 | 3 | const int N = 1e5+5; 4 | vector g[N]; 5 | int par[N], dep[N], sz[N]; 6 | map dist[N]; // Distancia entre dos nodos en el árbol original 7 | vector c_ans; // Respuesta optima de cada centroide hacía su subárbol 8 | 9 | int pre(int u, int p) { 10 | sz[u] = 1; 11 | for (auto &v : g[u]) 12 | if (!dep[v] && v != p) 13 | sz[u] += pre(v, u); 14 | return sz[u]; 15 | } 16 | 17 | int centroid(int u, int p, int k) { 18 | for (auto &v : g[u]) 19 | if (!dep[v] && v != p && sz[v] > k) 20 | return centroid(v, u, k); 21 | return u; 22 | } 23 | // Calcular información de cada centroide hacía los nodos de su subárbol 24 | void dfs(int u, int p, int c, int d = 0) { 25 | dist[c][u] = d; // Depende de lo que pida el problema 26 | for (auto &v : g[u]) { 27 | if (!dep[v] && v != p) { 28 | dfs(v, u, c, d+1); 29 | } 30 | } 31 | } 32 | // O(nlogn * k) En este ejemplo k = logn por el mapa dist en el dfs 33 | void build(int u, int p = -1, int d = 1) { 34 | int k = pre(u, p); 35 | int c = centroid(u, p, k/2); 36 | par[c] = p; dep[c] = d; 37 | dfs(c, p, c); 38 | for (auto &v : g[c]) 39 | if (!dep[v]) build(v, c, d+1); 40 | } 41 | // O(logn) lca de u y v en el árbol de centroides 42 | // La ruta de u a v en el árbol original pasa por este lca 43 | int lca(int u, int v) { 44 | for (; u != v; u = par[u]) 45 | if (dep[v] > dep[u]) swap(u, v); 46 | return u; 47 | } 48 | // O((logn)^2) Actualiza la respuesta de los ancestros de u 49 | void upd(int u) { 50 | for (int c = u; c != -1; c = par[c]) { 51 | c_ans[c] = min(c_ans[c], dist[c][u]); 52 | } 53 | } 54 | // O((logn)^2) Combina la respuesta del centroide c + el costo de c a u 55 | int query(int u) { 56 | int mn = N; 57 | for (int c = u; c != -1; c = par[c]) { 58 | mn = min(mn, c_ans[c] + dist[c][u]); 59 | } 60 | return mn; 61 | } 62 | -------------------------------------------------------------------------------- /c++/Data structures/Convex Hull Trick.cpp: -------------------------------------------------------------------------------- 1 | > Agregar líneas en orden no-creciente por pendiente m. Permite consultar el mínimo f(x). Para máximo, cambiar el signo de las lineas: -m, -h. 2 | 3 | typedef ll T; 4 | struct line { T m, h; }; 5 | struct cht { 6 | vector c; 7 | int pos = 0; 8 | 9 | T inter(line a, line b) { 10 | T x = b.h-a.h, y = a.m-b.m; 11 | return x/y + (x%y ? (x>0)==(y>0) : 0); // == ceil(x/y) 12 | } 13 | 14 | void add(T m, T h) { 15 | line l = {m, h}; 16 | if (c.size() && m == c.back().m) { 17 | l.h = min(h, c.back().h); 18 | c.pop_back(); if (pos) pos--; 19 | } 20 | while (c.size() > 1 && inter(c.back(), l) <= inter(c[c.size()-2], c.back())) { 21 | c.pop_back(); if (pos) pos--; 22 | } 23 | c.pb(l); 24 | } 25 | 26 | inline bool fbin(T x, int m) { return inter(c[m], c[m+1]) > x; } 27 | 28 | T query(T x) { 29 | // O(log n) query: 30 | int l = 0, r = c.size(); 31 | while (r-l > 1) { 32 | int m = (l+r)/2; 33 | if (fbin(x, m-1)) r = m; 34 | else l = m; 35 | } 36 | return c[l].m*x + c[l].h; 37 | // O(1) query (para x's ordenadas): 38 | while (pos > 0 && fbin(x, pos-1)) pos--; 39 | while (pos < (int)c.size()-1 && !fbin(x, pos)) pos++; 40 | return c[pos].m*x + c[pos].h; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /c++/Data structures/Disjoint Set.cpp: -------------------------------------------------------------------------------- 1 | > Permite mantener una colección de conjuntos disyuntos. find(u) indica a qué conjunto pertenece u. unite(u, v) une los conjuntos de u y v en uno. 2 | 3 | struct dsu { 4 | vector par, sz; 5 | int size; // Cantidad de conjuntos 6 | 7 | dsu(int n) : par(n), sz(n, 1) { 8 | size = n; 9 | iota(par.begin(), par.end(), 0); 10 | } 11 | // Busca el nodo representativo del conjunto de u 12 | int find(int u) { 13 | return par[u] == u ? u : (par[u] = find(par[u])); 14 | } 15 | // Une los conjuntos de u y v 16 | void unite(int u, int v) { 17 | u = find(u), v = find(v); 18 | if (u == v) return; 19 | if (sz[u] > sz[v]) swap(u, v); 20 | par[u] = v; 21 | sz[v] += sz[u]; 22 | size--; 23 | } 24 | // Cantidad de elementos en el conjunto de u 25 | int count(int u) { return sz[find(u)]; } 26 | }; 27 | -------------------------------------------------------------------------------- /c++/Data structures/Dsu on Tree (Sack).cpp: -------------------------------------------------------------------------------- 1 | > Util para responder queries del tipo "cuantos vertices en el subárbol de u cumplen con x propiedad" en O(nlogn * k) para todas las queries. 2 | > Esta implementación permite mantener una única estructura global agregando y quitando información. k es el costo de actualizar esa estructura global. 3 | > Problema de ejemplo: dado un árbol con los nodos coloreados, las consultas son: cuántos nodos del subárbol de u tienen color igual a c. 4 | 5 | const int N = 1e5+5; 6 | vector g[N]; 7 | int sz[N], big[N]; // big[u] = el hijo de u con mayor tamaño 8 | int col[N]; // Del problema de ejemplo 9 | int cnt[N]; // Estructura global del ejemplo 10 | 11 | int pre(int u, int p) { 12 | sz[u] = 1; big[u] = -1; 13 | int mx = 0; 14 | for (auto &v : g[u]) { 15 | if (v != p) { 16 | sz[u] += pre(v, u); 17 | if (sz[v] > mx) mx = sz[v], big[u] = v; 18 | } 19 | } 20 | return sz[u]; 21 | } 22 | 23 | void upd(int u, int p, int x) { 24 | cnt[col[u]] += x; // En el problema de ejemplo k = O(1) 25 | for (auto &v : g[u]) 26 | if (v != p && v != big[u]) 27 | upd(v, u, x); 28 | } 29 | 30 | void dfs(int u, int p, bool keep) { 31 | for (auto &v : g[u]) 32 | if (v != p && v != big[u]) 33 | dfs(v, u, false); 34 | if (big[u] != -1) dfs(big[u], u, true); 35 | // Agregar información del subárbol de los hijos de u != a big[u] 36 | upd(u, p, 1); 37 | // Aqui se responderían las queries 38 | // cnt[c] = cantidad de nodos del subárbol de u con color c 39 | big[u] = -1; 40 | if (!keep) upd(u, p, -1); // Quitar información del subárbol de u 41 | } 42 | -------------------------------------------------------------------------------- /c++/Data structures/Fenwick Tree.cpp: -------------------------------------------------------------------------------- 1 | > !! Usar indexando desde 1 en vez de 0. Permite procesar consultas de suma en rangos y actualizaciones puntuales sobre un arreglo. 2 | 3 | const int N = 1e5; 4 | int bit[N+1]; 5 | 6 | void add(int k, int val) { 7 | for (; k <= N; k += k&-k) bit[k] += val; 8 | } 9 | 10 | int rsq(int k) { 11 | int sum = 0; 12 | for (; k >= 1; k -= k&-k) sum += bit[k]; 13 | return sum; 14 | } 15 | 16 | int rsq(int i, int j) { return rsq(j) - rsq(i-1); } 17 | // Ultimo valor <= o < a val 18 | int lower_find(int val) { 19 | int id = 0; 20 | for (int i = 31-__builtin_clz(N); i >= 0; --i) { 21 | int nid = id | (1< !! Usar build() para inicializar. Para consultas sobre aristas: guardar el valor de cada arista en su nodo hijo y cambiar pos[u] por pos[u]+1 en la linea 55. 2 | > Agregar Segment Tree con un constructor vacío y actualizaciones puntuales. 3 | 4 | typedef int T; // Tipo de dato del segtree 5 | T neutro = 1e9; // "infinito", depende de la operación del segtree 6 | const int N = 1e5+5; 7 | vector g[N]; 8 | int par[N], dep[N], sz[N]; 9 | int pos[N], top[N], value[N]; 10 | vector arr; 11 | int idx; 12 | 13 | int pre(int u, int p, int d) { 14 | par[u] = p; dep[u] = d; 15 | int aux = 1; 16 | for (auto &v : g[u]) { 17 | if (v != p) { 18 | aux += pre(v, u, d+1); 19 | if (sz[v] >= sz[g[u][0]]) swap(v, g[u][0]); 20 | } 21 | } 22 | return sz[u] = aux; 23 | } 24 | 25 | void hld(int u, int p, int t) { 26 | arr[idx] = value[u]; 27 | pos[u] = idx++; 28 | top[u] = t < 0 ? t = u : t; 29 | for (auto &v : g[u]) { 30 | if (v != p) { 31 | hld(v, u, t); 32 | t = -1; 33 | } 34 | } 35 | } 36 | 37 | segtree sgt; 38 | 39 | void build(int n, int root) { 40 | idx = 0; 41 | arr.resize(n); 42 | pre(root, root, 0); 43 | hld(root, root, -1); 44 | sgt = segtree(arr); 45 | } 46 | 47 | T query(int u, int v) { 48 | T ans = neutro; 49 | while (top[u] != top[v]) { 50 | if (dep[top[u]] > dep[top[v]]) swap(u, v); 51 | ans = min(ans, sgt.query(pos[top[v]], pos[v])); 52 | v = par[top[v]]; 53 | } 54 | if (dep[u] > dep[v]) swap(u, v); 55 | ans = min(ans, sgt.query(pos[u], pos[v])); 56 | return ans; 57 | } 58 | 59 | void upd(int u, T val) { 60 | sgt.upd(pos[u], val); 61 | } 62 | -------------------------------------------------------------------------------- /c++/Data structures/Min queue.cpp: -------------------------------------------------------------------------------- 1 | > Funciona como una queue<> que además permite hallar el elemento mínimo en O(1). Para mantener el máximo: cambiar > por <. 2 | 3 | template 4 | struct mnque { 5 | deque dq, mn; 6 | 7 | void push(T x) { 8 | dq.pb(x); 9 | while (mn.size() && mn.back() > x) mn.pop_back(); // o < para max 10 | mn.pb(x); 11 | } 12 | 13 | void pop() { 14 | if (dq.front() == mn.front()) mn.pop_front(); 15 | dq.pop_front(); 16 | } 17 | 18 | T min() { return mn.front(); } 19 | }; 20 | 21 | mnque q; 22 | -------------------------------------------------------------------------------- /c++/Data structures/Ordered Set.cpp: -------------------------------------------------------------------------------- 1 | > Funciona como un set<> que además cuenta con dos funciones adicionales. 2 | 3 | #include 4 | #include 5 | using namespace __gnu_pbds; 6 | template 7 | using ordered_set = tree, rb_tree_tag, 8 | tree_order_statistics_node_update>; 9 | 10 | ordered_set st; 11 | st.find_by_order(k) // Retorna iterador al k-ésimo elemento más pequeño 12 | // Si k >= st.size() entonces retorna st.end() 13 | st.order_of_key(x) // Retorna cuántos elementos hay menores que x 14 | -------------------------------------------------------------------------------- /c++/Data structures/Persistent Segment Tree.cpp: -------------------------------------------------------------------------------- 1 | > Guarda el estado del segment tree después de cada actualización para permitir hacer consultas sobre estados pasados. 2 | > Consultas y actualizaciones en O(logn), ocupa O(nlogn) en memoria. 3 | 4 | struct node { 5 | node *left, *right; 6 | int val; 7 | 8 | node() : left(this), right(this), val(0) {} 9 | node(node *left, node *right, int val) : 10 | left(left), right(right), val(val) {} 11 | 12 | node* update(int l, int r, int i, int x) { 13 | if (l == r) return new node(nullptr, nullptr, val + x); 14 | int m = (l + r) / 2; 15 | if (i <= m) 16 | return new node(left->update(l, m, i, x), right, val + x); 17 | return new node(left, right->update(m + 1, r, i, x), val + x); 18 | } 19 | 20 | int query(int l, int r, int i, int j) { 21 | if (i > r || l > j) return 0; 22 | if (i <= l && r <= j) return this->val; 23 | int m = (l + r) / 2; 24 | int lf = left->query(l, m, i, j); 25 | int rg = right->query(m + 1, r, i, j); 26 | return lf + rg; 27 | } 28 | }; 29 | 30 | vector roots = {new node()}; 31 | roots.pb(roots.back()->update(0, n-1, i, x)); 32 | roots[i]->query(0, n-1, l, r); 33 | -------------------------------------------------------------------------------- /c++/Data structures/Segment Tree (Lazy Propagation).cpp: -------------------------------------------------------------------------------- 1 | > Dado un vector de valores permite hacer consultas sobre rangos y actualizaciones individuales en O(log n). Construcción en O(n). 2 | > Para hacer actualizaciones sobre rangos se deben descomentar las lineas de Lazy Propagation. 3 | > El valor neutro depende del tipo de consulta. Para sumas: 0, mínimos: infinito, máximos: -infinito, etc. 4 | 5 | typedef int T; // tipo de dato del segtree 6 | struct segtree { 7 | vector st; // , lazy; 8 | int n; T neutro = 1e9; // "infinito" 9 | 10 | segtree(const vector &v) { 11 | n = v.size(); 12 | st.assign(n*4, 0); 13 | // lazy.assign(n*4, neutro); 14 | build(1, 0, n-1, v); 15 | } 16 | 17 | void build(int p, int L, int R, const vector &v) { 18 | if (L == R) st[p] = v[L]; 19 | else { 20 | int m = (L+R)/2, l = p*2, r = l+1; 21 | build(l, L, m, v); 22 | build(r, m+1, R, v); 23 | st[p] = min(st[l], st[r]); 24 | } 25 | } 26 | /* 27 | void propagate(int p, int L, int R, T val) { 28 | if (val == neutro) return; 29 | st[p] = val; 30 | lazy[p] = neutro; 31 | if (L == R) return; 32 | int l = p*2, r = l+1; 33 | lazy[l] = lazy[r] = val; 34 | } 35 | */ 36 | T query(int i, int j) { return query(1, 0, n-1, i, j); } 37 | void upd(int i, int j, T val) { upd(1, 0, n-1, i, j, val); } 38 | 39 | T query(int p, int L, int R, int i, int j) { 40 | // propagate(p, L, R, lazy[p]); 41 | if (i > R || j < L) return neutro; 42 | if (i <= L && j >= R) return st[p]; 43 | int m = (L+R)/2, l = p*2, r = l+1; 44 | T lf = query(l, L, m, i, j); 45 | T rg = query(r, m+1, R, i, j); 46 | return min(lf, rg); 47 | } 48 | 49 | void upd(int p, int L, int R, int i, int j, T val) { 50 | // propagate(p, L, R, lazy[p]); 51 | if (i > R || j < L) return; 52 | if (i <= L && j >= R) st[p] = val; // cambiar por propagate(p, L, R, val); 53 | else { 54 | int m = (L+R)/2, l = p*2, r = l+1; 55 | upd(l, L, m, i, j, val); 56 | upd(r, m+1, R, i, j, val); 57 | st[p] = min(st[l], st[r]); 58 | } 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /c++/Data structures/Segment Tree 2D.cpp: -------------------------------------------------------------------------------- 1 | struct segtree { 2 | int n, m; 3 | T neutro = {1, 0, 0, true}; 4 | vector> st; 5 | 6 | segtree(int &n, int &m, vector> &a) : n(n), m(m) { 7 | st = vector>(2*n, vector(2*m, neutro)); 8 | build(n, m, a); 9 | } 10 | 11 | T get(T a, T b) { 12 | return max(a, b); 13 | } 14 | 15 | void build(int &n, int &m, vector> &a) { 16 | for (int i = 0; i < n; i++) 17 | for (int j = 0; j < m; j++) 18 | st[i + n][j + m] = a[i][j]; 19 | 20 | for (int i = 0; i < n; i++) 21 | for (int j = m - 1; j; j--) 22 | st[i + n][j] = get(st[i + n][j << 1], st[i + n][j << 1 | 1]); 23 | 24 | for (int i = n - 1; i; i--) 25 | for (int j = 0; j < 2*m; j++) 26 | st[i][j] = get(st[i << 1][j], st[i << 1 | 1][j]); 27 | } 28 | 29 | T query(int x1, int y1, int x2, int y2) { 30 | T ans = neutro; 31 | vector pos(2, 0); 32 | int node; 33 | for (x1 += n, x2 += n + 1; x1 < x2; x1 >>= 1, x2 >>= 1) { // rows 34 | node = 0; 35 | if (x1&1) pos[node++] = x1++; 36 | if (x2&1) pos[node++] = --x2; 37 | for (int it = 0; it < node; it++) { 38 | for (int l = y1 + m, r = y2 + m + 1; l < r; l >>= 1, r >>= 1) { // cols 39 | if (l&1) ans = get(ans, st[pos[it]][l++]); 40 | if (r&1) ans = get(ans, st[pos[it]][--r]); 41 | } 42 | } 43 | } 44 | return ans; 45 | } 46 | 47 | void upd(int l, int r, T val) { 48 | st[l + n][r + m] = val; 49 | for (int j = r + m; j; j >>= 1) 50 | st[l][j >> 1] = get(st[l][j], st[l][j + 1]); 51 | 52 | for (int i = l + n; i; i >>= 1) 53 | for (int j = r + m; j; j >>= 1) 54 | st[i >> 1][j] = get(st[i][j], st[i + 1][j]); 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /c++/Data structures/Sparse Table.cpp: -------------------------------------------------------------------------------- 1 | > Permite realizar consultas sobre rangos, no actualizaciones. 2 | > Soporta operaciones en las que no importa si se solapan los rangos, por ejemplo: max y min se pueden pero suma no. 3 | > Construcción y memoria O(nlon), consultas en O(1). 4 | 5 | const int N = 1e5+5; 6 | const int LG = log2(N)+1; 7 | int spt[LG][N]; 8 | int arr[N]; 9 | int n; 10 | 11 | void build() { 12 | for (int i = 0; i < n; i++) spt[0][i] = arr[i]; 13 | for (int j = 0; j < LG-1; j++) 14 | for (int i = 0; i+(1<<(j+1)) <= n; i++) 15 | spt[j+1][i] = min(spt[j][i], spt[j][i+(1< LIS; // PARA Lis_opt 8 | 9 | // LIS O(n^2).Si es non-decreasing cambiar (i > j) por (i >= j) 10 | int lis() { 11 | int best = -1; 12 | for (int i = 0; i < N; i++) { 13 | dp[i] = 1; 14 | for (int j = 0; j < i; j++) { 15 | if (A[i] > A[j]) dp[i] = max(dp[i], dp[j] + 1); 16 | } 17 | best = max(best, dp[i]); 18 | } 19 | return best; 20 | } 21 | 22 | // LIS O(nlog(n)) Para longest non-decreasing cambiar lower_bound por upper_bound 23 | int lis_opt() { 24 | LIS.clear(); 25 | for (int i = 0; i < N; i++) { 26 | auto id = lower_bound(LIS.begin(), LIS.end(), A[i]); 27 | if (id == LIS.end()) { 28 | LIS.pb(A[i]); 29 | dp[i] = LIS.size(); 30 | } 31 | else { 32 | int idx = id - LIS.begin(); 33 | LIS[idx] = A[i]; 34 | dp[i] = idx + 1; 35 | } 36 | } 37 | return LIS.size(); 38 | } 39 | 40 | // METODO PARA RECONSTRUIR LIS. Para non-decreasing cambiar < por <= 41 | stack rb; 42 | void build() { 43 | int k = LIS.size(); 44 | int cur = oo; 45 | for (int i = N - 1; i >= 0, k; i--) { 46 | if (A[i] < cur && k == dp[i]) { 47 | cur = A[i]; 48 | rb.push(A[i]); 49 | k--; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /c++/Dynamic programming/Max Range Sum.cpp: -------------------------------------------------------------------------------- 1 | Dada una lista de enteros, retorna la máxima suma de un rango de la lista. 2 | 3 | #include 4 | 5 | int maxRangeSum(vector a) { 6 | int sum = 0, ans = 0; 7 | for (int i = 0; i < a.size(); i++) { 8 | if (sum + a[i] >= 0) { 9 | sum += a[i]; 10 | ans = max(ans, sum); 11 | } else sum = 0; 12 | } 13 | return ans; 14 | } 15 | -------------------------------------------------------------------------------- /c++/Dynamic programming/Min Max Range.cpp: -------------------------------------------------------------------------------- 1 | Devuelve el el minimo de los maximos entre pares de rangos consecutivos haciendo cortes en el Array. 2 | 3 | const int MAX = 1005; 4 | ll dp[MAX][MAX]; 5 | ll sum_ran[MAX][MAX]; 6 | int N; 7 | 8 | ll f(int i, int cuts) { 9 | if (cuts == 0) return sum_ran[i][N-1]; 10 | if (i == N) return 0; 11 | ll &ans = dp[i][cuts]; 12 | if (ans != - 1) return ans; 13 | for (int j = i; j < N; j++) { 14 | ans = min(ans, max(sum_ran[i][j], f(i + 1, cuts - 1))); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /c++/Dynamic programming/Traveling Salesman Problem.cpp: -------------------------------------------------------------------------------- 1 | Problema del viajero. Devuelve la ruta minima haciendo un tour visitando todas los nodos (ciudades) una unica vez. 2 | 3 | const int MAX = 18; 4 | int target; // Inicializarlo para (1< rb; 9 | const int INF = (int) (2e9); 10 | 11 | // Llamar para TSP(0, -1) Si no empieza de ninguna ciudad especificia 12 | // De lo contrario llamar TSP(0, 0) 13 | int TSP(int mask, int u) { 14 | if (mask == target) { 15 | return 0; 16 | // O en su defecto el costo extra tras haber visitado todas las ciudades. EJ: Volver a la ciudad principal 17 | } 18 | if (u == -1) { 19 | int ans = INF; 20 | for (int i = 0; i < N; i++) { 21 | ans = min(ans, TSP(mask | (1< (const pt &o) const { return y > o.y || (y == o.y && x > o.x); } 16 | }; 17 | int cmp(lf a, lf b) { return (a + eps < b ? -1 :(b + eps < a ? 1 : 0)); } // double comparator 18 | 19 | T norm(pt a) { return a.x*a.x + a.y*a.y; } 20 | lf abs(pt a) { return sqrt(norm(a)); } 21 | lf arg(pt a) { return atan2(a.y, a.x); } 22 | pt unit(pt a) { return a/abs(a); } 23 | 24 | T dot(pt a, pt b) { return a.x*b.x + a.y*b.y; } // x = 90 -> cos = 0 25 | T cross(pt a, pt b) { return a.x*b.y - a.y*b.x; } // x = 180 -> sin = 0 26 | T orient(pt a, pt b, pt c) { return cross(b-a, c-a); } // clockwise = - 27 | pt rot(pt p, lf a) { return {p.x*cos(a) - p.y*sin(a), p.x*sin(a) + p.y*cos(a)}; } 28 | pt rotate_to_b(pt a, pt b, lf ang) { return rot(a-b, ang)+b; } // rotate by ang center b 29 | pt rot90ccw(pt p) { return {-p.y, p.x}; } 30 | pt rot90cw(pt p) { return {p.y, -p.x}; } 31 | pt translate(pt p, pt v) { return p+v; } 32 | pt scale(pt p, double f, pt c) { return c + (p-c)*f; } // c-center 33 | bool are_perp(pt v, pt w) { return dot(v, w) == 0; } 34 | int sign(T x) { return (T(0) < x) - (x < T(0)); } 35 | 36 | bool in_angle(pt a, pt b, pt c, pt x) { // x inside angle abc (center in a) 37 | assert(orient(a, b, c) != 0); 38 | if (orient(a, b, c) < 0) swap(b, c); 39 | return orient(a, b, x) >= 0 && orient(a, c, x) <= 0; 40 | } 41 | // angle bwn 2 vectors [0, pi] -> [0, 180] and (-pi, 0) -> (180, 360) 42 | lf angle(pt a, pt b) { return acos(max(-1.0, min(1.0, dot(a, b)/abs(a)/abs(b)))); } 43 | lf angle(pt a, pt b) { return atan2(cross(a, b), dot(a, b)); } 44 | lf angle360(pt a, pt b) { // [0, 360) 45 | lf ang = angle(a, b); return (ang < 0 ? ang+2*PI : ang) * 360/(2*PI); 46 | } 47 | // returns vector to transform points 48 | pt get_linear_transformation(pt p, pt q, pt r, pt fp, pt fq) { 49 | pt pq = q-p, num{cross(pq, fq-fp), dot(pq, fq-fp)}; 50 | return fp + pt{cross(r-p, num), dot(r-p, num)} / norm(pq); 51 | } 52 | bool half(pt p) { // true if is in (0, 180] (line is x axis) 53 | assert(p.x != 0 || p.y != 0); // the argument of (0, 0) is undefined 54 | return p.y > 0 || (p.y == 0 && p.x < 0); 55 | } 56 | bool half_from(pt p, pt v = {1, 0}) { // line is v (above v is true) 57 | return cross(v, p) < 0 || (cross(v, p) == 0 && dot(v, p) < 0); 58 | } 59 | bool polar_cmp(const pt &a, const pt &b) { // polar sort 60 | return make_tuple(half(a), 0) < make_tuple(half(b), cross(a, b)); 61 | // return make_tuple(half(a), 0, sq(a)) < make_tuple(half(b), cross(a, b), sq(b)); // further ones appear later 62 | } 63 | -------------------------------------------------------------------------------- /c++/Geometry/circle.cpp: -------------------------------------------------------------------------------- 1 | struct circle { 2 | pt c; T r; 3 | }; 4 | // (x-xo)^2 + (y-yo)^2 = r^2 5 | // circle that passes through abc 6 | circle center(pt a, pt b, pt c) { 7 | b = b-a, c = c-a; 8 | assert(cross(b, c) != 0); // no circumcircle if A, B, C aligned 9 | pt cen = a + rot90ccw(b*norm(c) - c*norm(b))/cross(b, c)/2; 10 | return {cen, abs(a-cen)}; 11 | } 12 | // centers of the circles that pass through ab and have radius r 13 | vector centers(pt a, pt b, T r) { 14 | if (abs(a-b) > 2*r + eps) return {}; 15 | pt m = (a+b)/2; 16 | double f = sqrt(r*r/norm(a-m) - 1); 17 | pt c = rot90ccw(a-m)*f; 18 | return {m-c, m+c}; 19 | } 20 | int inter_cl(circle c, line l, pair &out) { 21 | lf h2 = c.r*c.r - l.sq_dist(c.c); 22 | if (h2 >= 0) { // line touches circle 23 | pt p = l.proj(c.c); 24 | pt h = l.v*sqrt(h2)/abs(l.v); // vector of len h parallel to line 25 | out = {p-h, p+h}; 26 | } 27 | return 1 + sign(h2); // if 1 -> out.F == out.S 28 | } 29 | int inter_cc(circle c1, circle c2, pair &out) { 30 | pt d = c2.c-c1.c; 31 | double d2 = norm(d); 32 | if (d2 == 0) { assert(c1.r != c2.r); return 0; } // concentric circles (identical) 33 | double pd = (d2 + c1.r*c1.r - c2.r*c2.r)/2; // = |O_1P| * d 34 | double h2 = c1.r*c1.r - pd*pd/d2; // = h^2 35 | if (h2 >= 0) { 36 | pt p = c1.c + d*pd/d2, h = rot90ccw(d)*sqrt(h2/d2); 37 | out = {p-h, p+h}; 38 | } 39 | return 1 + sign(h2); 40 | } 41 | // circle-line inter = 1 42 | int tangents(circle c1, circle c2, bool inner, vector> &out) { 43 | if (inner) c2.r = -c2.r; // inner tangent 44 | pt d = c2.c-c1.c; 45 | double dr = c1.r-c2.r, d2 = norm(d), h2 = d2-dr*dr; 46 | if (d2 == 0 || h2 < 0) { assert(h2 != 0); return 0; } // (identical) 47 | for (double s : {-1, 1}) { 48 | pt v = (d*dr + rot90ccw(d)*sqrt(h2)*s)/d2; 49 | out.pb({c1.c + v*c1.r, c2.c + v*c2.r}); 50 | } 51 | return 1 + (h2 > 0); // if 1: circle are tangent 52 | } 53 | // circle targent passing through pt p 54 | int tangent_through_pt(pt p, circle c, pair &out) { 55 | double d = abs(p - c.c); 56 | if (d < c.r) return 0; 57 | pt base = c.c-p; 58 | double w = sqrt(norm(base) - c.r*c.r); 59 | pt a = {w, c.r}, b = {w, -c.r}; 60 | pt s = p + base*a/norm(base)*w; 61 | pt t = p + base*b/norm(base)*w; 62 | out = {s, t}; 63 | return 1 + (abs(c.c-p) == c.r); 64 | } 65 | -------------------------------------------------------------------------------- /c++/Geometry/halfplanes.cpp: -------------------------------------------------------------------------------- 1 | struct halfplane { 2 | double angle; 3 | pt p, pq; 4 | halfplane() {} 5 | halfplane(pt a, pt b): p(a), pq(b - a) { 6 | angle = atan2(pq.y, pq.x); 7 | } 8 | bool operator < (halfplane b) const { return angle < b.angle; } 9 | bool out(pt q) { return cross(pq, (q-p)) < -eps; } // checks if p is inside the half plane 10 | }; 11 | 12 | const lf inf = 1e100; 13 | // intersection pt of the lines of 2 halfplanes 14 | pt inter(halfplane& h1, halfplane& h2) { 15 | if (abs(cross(unit(h1.pq), unit(h2.pq))) <= eps) return {inf, inf}; 16 | lf alpha = cross((h2.p - h1.p), h2.pq) / cross(h1.pq, h2.pq); 17 | return h1.p + (h1.pq * alpha); 18 | } 19 | 20 | // intersection of halfplanes 21 | vector intersect(vector& b) { 22 | vector box = {{inf, inf}, {-inf, inf}, {-inf, -inf}, {inf, -inf}}; 23 | for (int i = 0; i < 4; i++) { 24 | b.pb({box[i], box[(i + 1) % 4]}); 25 | } 26 | sort(b.begin(), b.end()); 27 | int n = b.size(), q = 1, h = 0; 28 | vector c(n + 10); 29 | for (int i = 0; i < n; i++) { 30 | while (q < h && b[i].out(inter(c[h], c[h-1]))) h--; 31 | while (q < h && b[i].out(inter(c[q], c[q+1]))) q++; 32 | c[++h] = b[i]; 33 | if (q < h && abs(cross(c[h].pq, c[h-1].pq)) < eps) { 34 | if (dot(c[h].pq, c[h-1].pq) <= 0) return {}; 35 | h--; 36 | if (b[i].out(c[h].p)) c[h] = b[i]; 37 | } 38 | } 39 | while (q < h-1 && c[q].out(inter(c[h], c[h-1]))) h--; 40 | while (q < h-1 && c[h].out(inter(c[q], c[q+1]))) q++; 41 | if (h - q <= 1) return {}; 42 | c[h+1] = c[q]; 43 | vector s; 44 | for (int i = q; i < h+1; i++) s.pb(inter(c[i], c[i+1])); 45 | return s; 46 | } 47 | -------------------------------------------------------------------------------- /c++/Geometry/line.cpp: -------------------------------------------------------------------------------- 1 | struct line { 2 | pt v; T c; // v:direction c: pos in y axis 3 | line(pt v, T c) : v(v), c(c) {} 4 | line(T a, T b, T c) : v({b, -a}), c(c) {} // ax + by = c 5 | line(pt p, pt q) : v(q-p), c(cross(v, p)) {} 6 | T side(pt p) { return cross(v, p)-c; } 7 | lf dist(pt p) { return abs(side(p)) / abs(v); } 8 | lf sq_dist(pt p) { return side(p)*side(p) / (lf)norm(v); } 9 | line perp_through(pt p) { return {p, p + rot90ccw(v)}; } // line perp to v passing through p 10 | bool cmp_proj(pt p, pt q) { return dot(v, p) < dot(v, q); } // order for points over the line 11 | line translate(pt t) { return {v, c + cross(v, t)}; } 12 | line shift_left(double d) { return {v, c + d*abs(v)}; } 13 | pt proj(pt p) { return p - rot90ccw(v)*side(p)/norm(v); } // pt proyected on the line 14 | pt refl(pt p) { return p - rot90ccw(v)*2*side(p)/norm(v); } // pt reflected on the other side of the line 15 | }; 16 | 17 | bool inter_ll(line l1, line l2, pt &out) { 18 | T d = cross(l1.v, l2.v); 19 | if (d == 0) return false; 20 | out = (l2.v*l1.c - l1.v*l2.c) / d; // floating points 21 | return true; 22 | } 23 | // bisector divides the angle in 2 equal angles 24 | // interior line goes on the same direction as l1 and l2 25 | line bisector(line l1, line l2, bool interior) { 26 | assert(cross(l1.v, l2.v) != 0); // l1 and l2 cannot be parallel! 27 | lf sign = interior ? 1 : -1; 28 | return {l2.v/abs(l2.v) + l1.v/abs(l1.v) * sign, 29 | l2.c/abs(l2.v) + l1.c/abs(l1.v) * sign}; 30 | } 31 | -------------------------------------------------------------------------------- /c++/Geometry/segment.cpp: -------------------------------------------------------------------------------- 1 | bool in_disk(pt a, pt b, pt p) { // pt p inside ab disk 2 | return dot(a-p, b-p) <= 0; 3 | } 4 | bool on_segment(pt a, pt b, pt p) { // p on ab 5 | return orient(a, b, p) == 0 && in_disk(a, b, p); 6 | } 7 | // ab crossing cd 8 | bool proper_inter(pt a, pt b, pt c, pt d, pt &out) { 9 | T oa = orient(c, d, a), 10 | ob = orient(c, d, b), 11 | oc = orient(a, b, c), 12 | od = orient(a, b, d); 13 | // Proper intersection exists iff opposite signs 14 | if (oa*ob < 0 && oc*od < 0) { 15 | out = (a*ob - b*oa) / (ob-oa); 16 | return true; 17 | } 18 | return false; 19 | } 20 | // intersection bwn segments 21 | set inter_ss(pt a, pt b, pt c, pt d) { 22 | pt out; 23 | if (proper_inter(a, b, c, d, out)) return {out}; // if cross -> 1 24 | set s; 25 | if (on_segment(c, d, a)) s.insert(a); // a in cd 26 | if (on_segment(c, d, b)) s.insert(b); // b in cd 27 | if (on_segment(a, b, c)) s.insert(c); // c in ab 28 | if (on_segment(a, b, d)) s.insert(d); // d in ab 29 | return s; // 0, 2 30 | } 31 | lf pt_to_seg(pt a, pt b, pt p) { // p to ab 32 | if (a != b) { 33 | line l(a, b); 34 | if (l.cmp_proj(a, p) && l.cmp_proj(p, b)) // if closest to projection = (a, p, b) 35 | return l.dist(p); // output distance to line 36 | } 37 | return min(abs(p-a), abs(p-b)); // otherwise distance to A or B 38 | } 39 | lf seg_to_seg(pt a, pt b, pt c, pt d) { 40 | pt dummy; 41 | if (proper_inter(a, b, c, d, dummy)) return 0; // ab intersects cd 42 | return min({pt_to_seg(a, b, c), pt_to_seg(a, b, d), pt_to_seg(c, d, a), pt_to_seg(c, d, b)}); // try the 4 pts 43 | } 44 | -------------------------------------------------------------------------------- /c++/Graphs/2-satisfiability.cpp: -------------------------------------------------------------------------------- 1 | struct sat2 { 2 | int n; 3 | vector>> g; 4 | vector vis, val; 5 | vector comp; 6 | stack st; 7 | 8 | sat2(int n) : n(n), g(2, vector>(2*n)), vis(2*n), val(2*n), comp(2*n) { } 9 | 10 | int neg(int x) { return 2*n-x-1; } 11 | void make_true(int u) { add_edge(neg(u), u); } 12 | void make_false(int u) { make_true(neg(u)); } 13 | void add_or(int u, int v) { implication(neg(u), v); } 14 | void diff(int u, int v) { eq(u, neg(v)); } 15 | void eq(int u, int v) { 16 | implication(u, v); 17 | implication(v, u); 18 | } 19 | void implication(int u, int v) { 20 | add_edge(u, v); 21 | add_edge(neg(v), neg(u)); 22 | } 23 | 24 | void add_edge(int u, int v) { 25 | g[0][u].pb(v); 26 | g[1][v].pb(u); 27 | } 28 | 29 | void dfs(int id, int u, int t = 0) { 30 | vis[u] = true; 31 | for (auto &v : g[id][u]) 32 | if (!vis[v]) dfs(id, v, t); 33 | if (id) comp[u] = t; 34 | else st.push(u); 35 | } 36 | 37 | void kosaraju() { 38 | for (int u = 0; u < n; u++) { 39 | if (!vis[u]) dfs(0, u); 40 | if (!vis[neg(u)]) dfs(0, neg(u)); 41 | } 42 | vis.assign(2*n, false); 43 | int t = 0; 44 | while (!st.empty()) { 45 | int u = st.top(); st.pop(); 46 | if (!vis[u]) dfs(1, u, t++); 47 | } 48 | } 49 | 50 | bool check() { 51 | kosaraju(); 52 | for (int i = 0; i < n; i++) { 53 | if (comp[i] == comp[neg(i)]) return false; 54 | val[i] = comp[i] > comp[neg(i)]; 55 | } 56 | return true; 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /c++/Graphs/Articulation Bridges Biconnected.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo no dirigido halla los puntos de articulación, puentes y componentes biconexas. Para construir el block cut tree quitar los comentarios. 2 | 3 | struct edge { 4 | int u, v, comp; // A que componente biconexa pertenece 5 | bool bridge; // Si la arista es un puente 6 | }; 7 | 8 | const int MX = 1e5+5; // Cantidad maxima de nodos 9 | vector g[MX]; // Lista de adyacencia 10 | vector e; // Lista de aristas 11 | stack st; 12 | int low[MX], num[MX], cont; 13 | bool art[MX]; // Si el nodo es un punto de articulacion 14 | // vector> comps; // Componentes biconexas 15 | // vector> tree; // Block cut tree 16 | // vector id; // Id del nodo en el block cut tree 17 | int BCC; // Cantidad de componentes biconexas 18 | int n, m; // Cantidad de nodos y aristas 19 | 20 | void add_edge(int u, int v) { 21 | g[u].pb(e.size()); 22 | g[v].pb(e.size()); 23 | e.pb({u, v, -1, false}); 24 | } 25 | 26 | void dfs(int u, int p = -1) { 27 | low[u] = num[u] = cont++; 28 | for (auto &i : g[u]) { 29 | edge &ed = e[i]; 30 | int v = ed.u^ed.v^u; 31 | if (num[v] == -1) { 32 | st.push(i); 33 | dfs(v, i); 34 | if (low[v] > num[u]) 35 | ed.bridge = true; // bridge 36 | if (low[v] >= num[u]) { 37 | art[u] = (num[u] > 0 || num[v] > 1); // articulation 38 | int last; // start biconnected 39 | // comps.pb({}); 40 | do { 41 | last = st.top(); st.pop(); 42 | e[last].comp = BCC; 43 | // comps.back().insert(e[last].u); 44 | // comps.back().insert(e[last].v); 45 | } while (last != i); 46 | BCC++; // end biconnected 47 | } 48 | low[u] = min(low[u], low[v]); 49 | } else if (i != p && num[v] < num[u]) { 50 | st.push(i); 51 | low[u] = min(low[u], num[v]); 52 | } 53 | } 54 | } 55 | 56 | void build_tree() { 57 | tree.clear(); id.resize(n); 58 | for (int u = 0; u < n; u++) { 59 | if (art[u]) { 60 | id[u] = tree.size(); 61 | tree.pb({}); 62 | } 63 | } 64 | for (auto &comp : comps) { 65 | int node = tree.size(); 66 | tree.pb({}); 67 | for (auto &u : comp) { 68 | if (art[u]) { 69 | tree[id[u]].pb(node); 70 | tree[node].pb(id[u]); 71 | } else id[u] = node; 72 | } 73 | } 74 | } 75 | 76 | void init() { 77 | cont = BCC = 0; 78 | // comps.clear(); 79 | e.clear(); 80 | for (int i = 0; i <= n; i++) { 81 | g[i].clear(); 82 | num[i] = -1; // no visitado 83 | art[i] = false; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /c++/Graphs/BFS.cpp: -------------------------------------------------------------------------------- 1 | Busqueda en anchura sobre grafos. Recibe un nodo inicial u y visita todos los nodos alcanzables desde u. 2 | BFS tambien halla la distancia mas corta entre el nodo inicial u y los demas nodos si todas las aristas tienen peso 1. 3 | 4 | const int MX = 1e5+5; // Cantidad maxima de nodos 5 | vector g[MX]; // Lista de adyacencia 6 | vector dist; // Almacena la distancia a cada nodo 7 | int n, m; // Cantidad de nodos y aristas 8 | 9 | void bfs(int u) { 10 | queue q; 11 | q.push(u); 12 | dist[u] = 0; 13 | 14 | while (q.size()) { 15 | u = q.front(); 16 | q.pop(); 17 | for (auto &v : g[u]) { 18 | if (dist[v] == -1) { 19 | dist[v] = dist[u] + 1; 20 | q.push(v); 21 | } 22 | } 23 | } 24 | } 25 | 26 | void init() { 27 | dist.assign(n, -1); 28 | for (int i = 0; i <= n; i++) { 29 | g[i].clear(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /c++/Graphs/Bellman Ford.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo con pesos, positivos o negativos, halla la ruta de costo minimo entre un nodo inicial u y todos los demas nodos. 2 | Tambien halla ciclos negativos. 3 | 4 | const ll inf = 1e18; 5 | const int MX = 1e5+5; // Cantidad maxima de nodos 6 | vector g[MX]; // Lista de adyacencia, u->[(v, cost)] 7 | vector dist; // Almacena la distancia a cada nodo 8 | // vector cycle; // Para construir el ciclo negativo 9 | int n, m; // Cantidad de nodos y aristas 10 | 11 | // O(n*m) 12 | void bellmanFord(int src) { 13 | dist.assign(n, inf); 14 | dist[src] = 0; 15 | for (int i = 0; i < n-1; i++) 16 | for (int u = 0; u < n; u++) 17 | if (dist[u] != inf) 18 | for (auto &v : g[u]) { 19 | dist[v.F] = min(dist[v.F], dist[u] + v.S); 20 | } 21 | // Encontrar ciclos negativos 22 | // cycle.clear(); 23 | for (int u = 0; u < n; u++) 24 | if (dist[u] != inf) 25 | for (auto &v : g[u]) 26 | if (dist[v.F] > dist[u] + v.S) { // Ciclo negativo 27 | dist[v.F] = -inf; 28 | // cycle.pb(v.F); // Para reconstruir 29 | } 30 | } 31 | 32 | void init() { 33 | for (int i = 0; i <= n; i++) { 34 | g[i].clear(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /c++/Graphs/Bipartite Check.cpp: -------------------------------------------------------------------------------- 1 | Modificacion del BFS para detectar si un grafo es bipartito. 2 | 3 | const int MX = 1e5+5; // Cantidad maxima de nodos 4 | vector g[MX]; // Lista de adyacencia 5 | vector color; // Almacena el color de cada nodo 6 | bool bipartite; // true si el grafo es bipartito 7 | int n, m; // Cantidad de nodos y aristas 8 | 9 | void bfs(int u) { 10 | queue q; 11 | q.push(u); 12 | color[u] = 0; 13 | 14 | while (q.size()) { 15 | u = q.front(); 16 | q.pop(); 17 | for (auto &v : g[u]) { 18 | if (color[v] == -1) { 19 | color[v] = 1-color[u]; 20 | q.push(v); 21 | } else if (color[v] == color[u]) { 22 | bipartite = false; 23 | return; 24 | } 25 | } 26 | } 27 | } 28 | 29 | void init() { 30 | bipartite = true; 31 | color.assign(n, -1); 32 | for (int i = 0; i <= n; i++) { 33 | g[i].clear(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /c++/Graphs/Cycle Detection.cpp: -------------------------------------------------------------------------------- 1 | Determina si un grafo dirigido tiene o no ciclos (si es un DAG o no). 2 | 3 | const int MX = 1e5+5; // Cantidad maxima de nodos 4 | vector g[MX]; // Lista de adyacencia 5 | vector vis; // Marca el estado de los nodos ya visitados 6 | bool cycle; // true si el grafo tiene ciclos 7 | int n, m; // Cantidad de nodos y aristas 8 | 9 | void dfs(int u) { 10 | if (cycle) return; 11 | vis[u] = 1; 12 | for (auto &v : g[u]) { 13 | if (!vis[v]) dfs(v); 14 | else if (vis[v] == 1) { 15 | cycle = true; 16 | break; 17 | } 18 | } 19 | vis[u] = 2; 20 | } 21 | 22 | void init() { 23 | vis.assign(n, 0); 24 | for (int i = 0; i <= n; i++) { 25 | g[i].clear(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /c++/Graphs/DFS.cpp: -------------------------------------------------------------------------------- 1 | Busqueda en profundidad sobre grafos. Recibe un nodo inicial u y visita todos los nodos alcanzables desde u. 2 | DFS puede ser usado para contar la cantidad de componentes conexas en un grafo y puede ser modificado para que retorne informacion de los nodos dependiendo del problema. 3 | 4 | const int MX = 1e5+5; // Cantidad maxima de nodos 5 | vector g[MX]; // Lista de adyacencia 6 | vector vis; // Marca los nodos ya visitados 7 | int n, m; // Cantidad de nodos y aristas 8 | 9 | void dfs(int u) { 10 | vis[u] = true; 11 | for (auto &v : g[u]) { 12 | if (!vis[v]) dfs(v); 13 | } 14 | } 15 | 16 | void init() { 17 | vis.assign(n, false); 18 | for (int i = 0; i <= n; i++) { 19 | g[i].clear(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /c++/Graphs/Dijkstra.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo con pesos no negativos halla la ruta de costo minimo entre un nodo inicial u y todos los demas nodos. 2 | 3 | struct edge { 4 | int v; ll w; 5 | bool operator < (const edge &o) const { 6 | return o.w < w; // invertidos para que la pq ordene de < a > 7 | } 8 | }; 9 | 10 | const ll inf = 1e18; 11 | const int MX = 1e5+5; // Cantidad maxima de nodos 12 | vector g[MX]; // Lista de adyacencia 13 | vector vis; // Marca los nodos ya visitados 14 | vector dist; // Almacena la distancia a cada nodo 15 | int pre[MX]; // Almacena el nodo anterior para construir las rutas 16 | int n, m; // Cantidad de nodos y aristas 17 | 18 | void dijkstra(int u) { 19 | priority_queue pq; 20 | pq.push({u, 0}); 21 | dist[u] = 0; 22 | 23 | while (pq.size()) { 24 | u = pq.top().v; pq.pop(); 25 | if (!vis[u]) { 26 | vis[u] = true; 27 | for (auto &ed : g[u]) { 28 | int v = ed.v; 29 | if (!vis[v] && dist[v] > dist[u] + ed.w) { 30 | dist[v] = dist[u] + ed.w; 31 | pre[v] = u; 32 | pq.push({v, dist[v]}); 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | void init() { 40 | vis.assign(n, false); 41 | dist.assign(n, inf); 42 | for (int i = 0; i <= n; i++) { 43 | g[i].clear(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /c++/Graphs/Flood Fill.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo implicito como matriz, "colorea" y cuenta el tamaño de las componentes conexas. 2 | Esta funcion debe ser llamada con las coordenadas (i, j) donde se inicia el recorrido, busca cada caracter c1 de la componente, los remplaza por el caracter c2 y retorna el tamaño. 3 | 4 | const int MX = 1e3; // Tamanio maximo de la matriz 5 | int dy[] = {1, 1, 0,-1,-1,-1, 0, 1}; // Posibles movimientos: 6 | int dx[] = {0, 1, 1, 1, 0,-1,-1,-1}; // (8 direcciones) 7 | char grid[MX][MX]; // Matriz de caracteres 8 | int n, m; // Tamanio de la matriz 9 | 10 | int floodfill(int y, int x, char c1, char c2) { 11 | if (y < 0 || y >= n || x < 0 || x >= m) return 0; 12 | if (grid[y][x] != c1) return 0; 13 | grid[y][x] = c2; 14 | int ans = 1; 15 | for (int i = 0; i < 8; i++) { 16 | ans += floodfill(y + dy[i], x + dx[i], c1, c2); 17 | } 18 | return ans; 19 | } 20 | -------------------------------------------------------------------------------- /c++/Graphs/Floyd Warshall.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo halla la distancia minima entre cualquier par de nodos. g[i][j] guardara la distancia minima entre el nodo i y el j. 2 | 3 | const int inf = 1e9; 4 | const int MX = 505; // Cantidad maxima de nodos 5 | int g[MX][MX]; // Matriz de adyacencia 6 | int n, m; // Cantidad de nodos y aristas 7 | 8 | void floydWarshall() { 9 | for (int k = 0; k < n; k++) 10 | for (int i = 0; i < n; i++) 11 | for (int j = 0; j < n; j++) 12 | g[i][j] = min(g[i][j], g[i][k] + g[k][j]); 13 | } 14 | 15 | void init() { 16 | for (int i = 0; i <= n; i++) { 17 | for (int j = 0; j <= n; j++) { 18 | g[i][j] = (i == j ? 0 : inf); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /c++/Graphs/Kruskal.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo con pesos halla su arbol cobertor minimo. Debe agregarse Disjoint Set. 2 | 3 | struct edge { int u, v, w; }; 4 | 5 | bool cmp(edge &a, edge &b) { 6 | return a.w < b.w; 7 | } 8 | 9 | const int MX = 1e5+5; // Cantidad maxima de nodos 10 | vector g[MX]; // Lista de adyacencia 11 | vector e; // Lista de aristas 12 | int n, m; // Cantidad de nodos y aristas 13 | 14 | void kruskall() { 15 | sort(e.begin(), e.end(), cmp); 16 | dsu ds(n); 17 | int cnt = 0; 18 | for (auto &ed : e) { 19 | if (ds.find(ed.u) != ds.find(ed.v)) { 20 | ds.unite(ed.u, ed.v); 21 | g[ed.u].pb({ed.v, ed.w}); 22 | g[ed.v].pb({ed.u, ed.w}); 23 | if (++cnt == n-1) break; 24 | } 25 | } 26 | } 27 | 28 | void init() { 29 | e.clear(); 30 | for (int i = 0; i <= n; i++) { 31 | g[i].clear(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /c++/Graphs/Lowest Common Ancestor.cpp: -------------------------------------------------------------------------------- 1 | Dados los nodos u y v de un arbol determina cual es el ancestro comun mas bajo entre u y v. 2 | *Tambien puede determinar la arista de peso maximo/minimo entre los nodos u y v (Para esto quitar los "//") 3 | Se debe ejecutar la funcion dfs() primero, el padre de la raiz es sí mismo, w es el valor a almacenar del padre. 4 | 5 | const int N = 4e5+2, inf = 1e9, LOG2 = 20; 6 | int dep[N]; // Profundidad de cada nodo 7 | int par[LOG2][N]; // Sparse table para guardar los padres 8 | // int rmq[LOG2][N]; // Sparse table para guardar pesos 9 | 10 | struct edge { int v, w; }; 11 | vector g[N]; 12 | 13 | void dfs(int u, int p, int d, int w) { 14 | dep[u] = d; 15 | par[0][u] = p; 16 | // rmq[0][u] = w; 17 | for (int j = 1; j < LOG2; j++) { 18 | par[j][u] = par[j-1][par[j-1][u]]; 19 | // rmq[j][u] = max(rmq[j-1][u], rmq[j-1][par[j-1][u]]); 20 | } 21 | for (auto &ed: g[u]) { 22 | int v = ed.v; 23 | int val = ed.w; 24 | if (v == p)continue; 25 | dfs(v, u, d+1, val); 26 | } 27 | } 28 | 29 | int lca(int u, int v) { 30 | // int ans = -1; 31 | if (dep[v] < dep[u])swap(u, v); 32 | int d = dep[v]-dep[u]; 33 | for (int j = LOG2-1; j >= 0; j--) { 34 | if (d >> j & 1) { 35 | // ans = max(ans, rmq[j][v]); 36 | v = par[j][v]; 37 | } 38 | } 39 | // if (u == v) return ans; 40 | if (u == v) return u; 41 | for (int j = LOG2-1; j >= 0; j--) { 42 | if (par[j][u] != par[j][v]) { 43 | // ans = max({ans, rmq[j][u], rmq[j][v]}); 44 | u = par[j][u]; 45 | v = par[j][v]; 46 | } 47 | } 48 | // return max({ans, rmq[1][u], rmq[0][v]}); // si la info es de los nodos 49 | // return max({ans, rmq[0][u], rmq[0][v]}); // si la info es de las aristas 50 | return par[0][u]; 51 | } 52 | -------------------------------------------------------------------------------- /c++/Graphs/Prim.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo halla el costo total de su arbol cobertor minimo. 2 | 3 | struct edge { 4 | int v; ll w; 5 | 6 | bool operator < (const edge &o) const { 7 | return o.w < w; // invertidos para que la pq ordene de < a > 8 | } 9 | }; 10 | 11 | const int MX = 1e5+5; // Cantidad maxima de nodos 12 | vector g[MX]; // Lista de adyacencia 13 | vector vis; // Marca los nodos ya visitados 14 | ll ans; // Costo total del arbol cobertor minimo 15 | int n, m; // Cantidad de nodos y aristas 16 | 17 | void prim() { 18 | priority_queue pq; 19 | vis[0] = true; 20 | for (auto &ed : g[0]) { 21 | int v = ed.v; 22 | if (!vis[v]) pq.push({v, ed.w}); 23 | } 24 | while (pq.size()) { 25 | int u = pq.top().v; 26 | ll w = pq.top().w; 27 | pq.pop(); 28 | if (!vis[u]) { 29 | ans += w; 30 | vis[u] = true; 31 | for (auto &ed : g[u]) { 32 | int v = ed.v; 33 | if (!vis[v]) pq.push({v, ed.w}); 34 | } 35 | } 36 | } 37 | } 38 | 39 | void init() { 40 | ans = 0; 41 | vis.assign(n, false); 42 | for (int i = 0; i <= n; i++) { 43 | g[i].clear(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /c++/Graphs/Tarjan.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo dirigido halla las componentes fuertemente conexas (SCC). 2 | 3 | const int inf = 1e9; 4 | const int MX = 1e5+5; // Cantidad maxima de nodos 5 | vector g[MX]; // Lista de adyacencia 6 | stack st; 7 | int low[MX], pre[MX], cnt; 8 | int comp[MX]; // Almacena la componente a la que pertenece cada nodo 9 | int SCC; // Cantidad de componentes fuertemente conexas 10 | int n, m; // Cantidad de nodos y aristas 11 | 12 | void tarjan(int u) { 13 | low[u] = pre[u] = cnt++; 14 | st.push(u); 15 | for (auto &v : g[u]) { 16 | if (pre[v] == -1) tarjan(v); 17 | low[u] = min(low[u], low[v]); 18 | } 19 | if (low[u] == pre[u]) { 20 | while (true) { 21 | int v = st.top(); st.pop(); 22 | low[v] = inf; 23 | comp[v] = SCC; 24 | if (u == v) break; 25 | } 26 | SCC++; 27 | } 28 | } 29 | 30 | void init() { 31 | cnt = SCC = 0; 32 | for (int i = 0; i <= n; i++) { 33 | g[i].clear(); 34 | pre[i] = -1; // no visitado 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /c++/Graphs/Topological Sort.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo aciclico dirigido (DAG), ordena los nodos linealmente de tal manera que si existe una arista entre los nodos u y v entonces u aparece antes que v. 2 | Este ordenamiento es una manera de poner todos los nodos en una linea recta de tal manera que las aristas vayan de izquierda a derecha. 3 | 4 | const int MX = 1e5+5; // Cantidad maxima de nodos 5 | vector g[MX]; // Lista de adyacencia 6 | vector vis; // Marca los nodos ya visitados 7 | deque order; // Orden topologico del grafo 8 | int n, m; // Cantidad de nodos y aristas 9 | 10 | void toposort(int u) { 11 | vis[u] = true; 12 | for (auto &v : g[u]) { 13 | if (!vis[v]) toposort(v); 14 | } 15 | order.push_front(u); 16 | } 17 | 18 | void init() { 19 | order.clear(); 20 | vis.assign(n, false); 21 | for (int i = 0; i <= n; i++) { 22 | g[i].clear(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /c++/Graphs/Tree Isomorphism.cpp: -------------------------------------------------------------------------------- 1 | Permite hashear árboles para comparar su estructura rápidamente. 2 | Agregar Random Integer para ll 3 | 4 | map table; 5 | 6 | ll get(ll x) { 7 | if (table.count(x)) return table[x]; 8 | return table[x] = rand(0, 1e18); 9 | } 10 | 11 | ll hashes[N], sum[N]; 12 | 13 | void dfs(int u, int p) { 14 | sum[u] = 0; 15 | for (auto &v : g[u]) { 16 | if (v == p) continue; 17 | dfs(v, u); 18 | sum[u] += hashes[v]; 19 | } 20 | hashes[u] = get(sum[u]); 21 | } 22 | -------------------------------------------------------------------------------- /c++/Math/Basis of a Vector Space (mod 2 Field).cpp: -------------------------------------------------------------------------------- 1 | Dado un arreglo A con n numeros calcula en basis[] las mascaras con las cuales se pueden generar todos los diferentes xor que se generan al hacer xor entre los elementos de cualquier subconjunto A. La cantidad de xor diferentes es 2^sz. 2 | 3 | const int D = 30; // maxima cantidad de bits 4 | int basis[D]; 5 | int sz; // cantidad de mascaras en la base 6 | 7 | // O(n*D) 8 | void insertVector(int mask) { 9 | for (int i = 0; i < D; ++i) { 10 | if (mask & (1< f; 5 | fact(n, f); 6 | ll ans = 1; 7 | for (auto p : f) { 8 | ans *= (exp(p.first, p.second+1)-1)/(p.first-1); 9 | } 10 | return ans; 11 | } 12 | 13 | * Calcula la cantidad de divisores de n. Agregar Prime Factorization. 14 | 15 | ll cantDiv(ll n) { 16 | map f; 17 | fact(n, f); 18 | ll ans = 1; 19 | for (auto p : f) ans *= (p.second + 1); 20 | return ans; 21 | } 22 | 23 | * Calcular la cantidad de divisores para todos los numeros menores o iguales a MX con Sieve of Eratosthenes. 24 | 25 | const int MX = 1e6; 26 | bool marked[MX+1]; 27 | vector cnt; 28 | 29 | void sieve() { 30 | cnt.assign(MX+1, 1); 31 | marked[0] = marked[1] = true; 32 | for (int i = 2; i <= MX; i++) { 33 | if (marked[i]) continue; 34 | cnt[i]++; 35 | for (int j = i*2; j <= MX ; j += i) { 36 | int n = j, c = 1; 37 | while (n%i == 0) n /= i, c++; 38 | cnt[j] *= c; 39 | marked[j] = true; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /c++/Math/Euler Totient.cpp: -------------------------------------------------------------------------------- 1 | La funcion phi de Euler devuelve la cantidad de enteros positivos menores o iguales a n que son coprimos con n (gcd(n, i) = 1) 2 | 3 | // O(sqrt(n)) 4 | ll phi(ll n) { 5 | ll ans = n; 6 | for (int p = 2; p <= n/p; ++p) { 7 | if (n % p == 0) ans -= ans / p; 8 | while (n % p == 0) n /= p; 9 | } 10 | if (n > 1) ans -= ans / n; 11 | return ans; 12 | } 13 | 14 | * Calcular el Euler totient para todos los numeros menores o iguales a MX con Sieve of Eratosthenes. 15 | 16 | const int MX = 1e6; 17 | bool marked[MX+1]; 18 | int phi[MX+1]; 19 | // O(MX log(log(MX))) 20 | void sieve() { 21 | iota(phi, phi+MX+1, 0); 22 | marked[0] = marked[1] = true; 23 | for (int i = 2; i <= MX; i++) { 24 | if (marked[i]) continue; 25 | for (int j = i; j <= MX ; j += i) { 26 | phi[j] -= phi[j] / i; 27 | marked[j] = true; 28 | } 29 | marked[i] = false; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /c++/Math/Extended Euclides.cpp: -------------------------------------------------------------------------------- 1 | El algoritmo de Euclides extendido retorna el gcd(a, b) y calcula los coeficientes enteros X y Y que satisfacen la ecuacion: a*X + b*Y = gcd(a, b). 2 | 3 | int x, y; 4 | // O(log(max(a, b))) 5 | int euclid(int a, int b) { 6 | if (b == 0) { x = 1; y = 0; return a; } 7 | int d = euclid(b, a%b); 8 | int aux = x; 9 | x = y; 10 | y = aux - a/b*y; 11 | return d; 12 | } 13 | -------------------------------------------------------------------------------- /c++/Math/Fast Fourier Transform.cpp: -------------------------------------------------------------------------------- 1 | Multiplicacion de polinomios en O(n log n) 2 | 3 | const double PI = acos(-1.0); 4 | 5 | namespace fft { 6 | struct pt { 7 | double r, i; 8 | pt(double r = 0.0, double i = 0.0) : r(r), i(i) {} 9 | pt operator + (const pt &b) { return pt(r+b.r, i+b.i); } 10 | pt operator - (const pt &b) { return pt(r-b.r, i-b.i); } 11 | pt operator * (const pt &b) { return pt(r*b.r - i*b.i, r*b.i + i*b.r); } 12 | }; 13 | vector rev; 14 | 15 | void fft(vector &y, int on) { 16 | int n = y.size(); 17 | for (int i = 1; i < n; i++) 18 | if (i < rev[i]) swap(y[i], y[rev[i]]); 19 | for (int m = 2; m <= n; m <<= 1) { 20 | double ang = -on * 2 * PI / m; 21 | pt wm(cos(ang), sin(ang)); 22 | for (int k = 0; k < n; k += m) { 23 | pt w(1, 0); 24 | for (int j = 0; j < m / 2; j++) { 25 | pt u = y[k + j]; 26 | pt t = w * y[k + j + m / 2]; 27 | y[k + j] = u + t; 28 | y[k + j + m / 2] = u - t; 29 | w = w * wm; 30 | } 31 | } 32 | } 33 | if (on == -1) for (int i = 0; i < n; i++) y[i].r /= n; 34 | } 35 | 36 | vector mul(vector &a, vector &b) { 37 | int n = 1, t = 0, la = a.size(), lb = b.size(); 38 | for (; n <= (la+lb+1); n <<= 1, t++); t = 1<<(t-1); 39 | vector x1(n), x2(n); 40 | rev.assign(n, 0); 41 | for (int i = 0; i < n; i++) rev[i] = rev[i >> 1] >> 1 | (i & 1 ? t : 0); 42 | for (int i = 0; i < la; i++) x1[i] = pt(a[i], 0); 43 | for (int i = 0; i < lb; i++) x2[i] = pt(b[i], 0); 44 | fft(x1, 1); fft(x2, 1); 45 | for (int i = 0; i < n; i++) x1[i] = x1[i] * x2[i]; 46 | fft(x1, -1); 47 | vector ans(n); 48 | for (int i = 0; i < n; i++) ans[i] = x1[i].r + 0.5; 49 | return ans; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /c++/Math/Fraction.cpp: -------------------------------------------------------------------------------- 1 | Estructura para trabajar con fracciones como un tipo de dato 2 | 3 | typedef ll T; 4 | struct Fraction { 5 | T num, den; 6 | 7 | Fraction() : num(0), den(1) {} 8 | Fraction(T n) : num(n), den(1) {} 9 | Fraction(T n, T d) : num(n), den(d) { reduce(); } 10 | 11 | void reduce() { 12 | assert(den != 0); 13 | T gcd = __gcd(num, den); 14 | num /= gcd, den /= gcd; 15 | if (den < 0) num = -num, den = -den; 16 | } 17 | Fraction fractional_part() const { // x - floor(x) 18 | Fraction fp = Fraction(num % den, den); 19 | if (fp < Fraction(0)) fp += Fraction(1); 20 | return fp; 21 | } 22 | T compare(Fraction f) const { 23 | return num * f.den - den * f.num; 24 | } 25 | Fraction operator + (const Fraction& f) { 26 | return Fraction(num * f.den + den * f.num, den * f.den); 27 | } 28 | Fraction operator - (const Fraction& f) { 29 | return Fraction(num * f.den - den * f.num, den * f.den); 30 | } 31 | Fraction operator * (const Fraction& f) { 32 | Fraction a = Fraction(num, f.den); 33 | Fraction b = Fraction(f.num, den); 34 | return Fraction(a.num * b.num, a.den * b.den); 35 | } 36 | Fraction operator / (const Fraction& f) { 37 | return *this * Fraction(f.den, f.num); 38 | } 39 | Fraction operator += (const Fraction& f) { return *this = *this + f; } 40 | Fraction operator -= (const Fraction& f) { return *this = *this - f; } 41 | Fraction operator *= (const Fraction& f) { return *this = *this * f; } 42 | Fraction operator /= (const Fraction& f) { return *this = *this / f; } 43 | bool operator == (const Fraction& f) const { return compare(f) == 0; } 44 | bool operator != (const Fraction& f) const { return compare(f) != 0; } 45 | bool operator >= (const Fraction& f) const { return compare(f) >= 0; } 46 | bool operator <= (const Fraction& f) const { return compare(f) <= 0; } 47 | bool operator > (const Fraction& f) const { return compare(f) > 0; } 48 | bool operator < (const Fraction& f) const { return compare(f) < 0; } 49 | }; 50 | Fraction operator - (const Fraction& f) { return Fraction(-f.num, f.den); } 51 | ostream& operator << (ostream& os, const Fraction& f) { 52 | return os << "(" << (ll)f.num << "/" << (ll)f.den << ")"; 53 | } 54 | -------------------------------------------------------------------------------- /c++/Math/Gauss Jordan.cpp: -------------------------------------------------------------------------------- 1 | Algoritmo de eliminación Gauss-Jordan O(N ^ 3) 2 | Soluciona un sistema de ecuaciones de la forma: 3 | a11 x1 + a12 x2 + ... + a1m xm = b1 4 | a21 x1 + a22 x2 + ... + a2m xm = b2 5 | an x1 + an2 x2 + ... + anm xm = bn 6 | 7 | El vector a contiene los valores de la matriz, cada fila es una ecuación, la última columna contiene los valores b. 8 | 9 | const int EPS = 1; 10 | int gauss(vector>& a, vector &ans) { 11 | int n = a.size(), m = a[0].size()-1; 12 | vector where(m, -1); 13 | for (int col = 0, row = 0; col < m && row < n; ++col) { 14 | int sel = row; 15 | for (int i = row; i < n; ++i) 16 | if (abs(a[i][col]) > abs(a[sel][col])) sel = i; 17 | if (abs(a[sel][col]) < EPS) continue; 18 | swap(a[sel], a[row]); 19 | where[col] = row; 20 | for (int i = 0; i < n; ++i) 21 | if (i != row) { 22 | int c = divide(a[i][col], a[row][col]); 23 | for (int j = col; j <= m; ++j) 24 | a[i][j] = sub(a[i][j], mul(a[row][j], c)); 25 | } 26 | ++row; 27 | } 28 | ans.assign(m, 0); 29 | for (int i = 0; i < m; ++i) 30 | if (where[i] != -1) ans[i] = divide(a[where[i]][m], a[where[i]][i]); 31 | for (int i = 0; i < n; ++i) { 32 | int sum = 0; 33 | for (int j = 0; j < m; ++j) 34 | sum = add(sum, mul(ans[j], a[i][j])); 35 | if (sum != a[i][m]) return 0; 36 | } 37 | for (int i = 0; i < m; ++i) 38 | if (where[i] == -1) return -1; 39 | return 1; 40 | } 41 | 42 | 43 | Gauss jordan para operaciones de xor 44 | 45 | int gauss(vector> &a, vector> &b, int n, int m, vector> &ans) { 46 | vector where(m, -1); 47 | for (int col = 0, row = 0; col < m && row < n; ++col) { 48 | for (int i = row; i < n; ++i) { 49 | if (a[i][col]) { 50 | swap(a[i], a[row]); 51 | swap(b[i], b[row]); 52 | break; 53 | } 54 | } 55 | if (!a[row][col])continue; 56 | where[col] = row; 57 | for (int i = 0; i < n; ++i) 58 | if (i != row && a[i][col]) { 59 | a[i] ^= a[row]; 60 | b[i] ^= b[row]; 61 | } 62 | ++row; 63 | } 64 | ans.assign(m, 0); 65 | for (int i = 0; i < m; ++i) 66 | if (where[i] != -1) ans[i] = b[where[i]]; 67 | for (int i = 0; i < n; ++i) { 68 | if (ans[i] == 0) return 0; 69 | } 70 | for (int i = 0; i < m; ++i) 71 | if (where[i] == -1) return -1; // infinite solutions 72 | return 1; 73 | } 74 | -------------------------------------------------------------------------------- /c++/Math/Greatest Common Divisor.cpp: -------------------------------------------------------------------------------- 1 | Calcula el maximo comun divisor entre a y b mediante el algoritmo de Euclides. Tambien se puede usar __gcd(a, b). 2 | 3 | // O(log(max(a, b))) 4 | int gcd(int a, int b) { 5 | return b == 0 ? a : gcd(b, a%b); 6 | } 7 | -------------------------------------------------------------------------------- /c++/Math/Lowest Common Multiple.cpp: -------------------------------------------------------------------------------- 1 | Calculo del minimo comun multiplo usando el maximo comun divisor. 2 | 3 | // O(log(max(a, b))) 4 | int lcm(int a, int b) { 5 | return a / __gcd(a, b) * b; 6 | } 7 | -------------------------------------------------------------------------------- /c++/Math/Miller Rabin.cpp: -------------------------------------------------------------------------------- 1 | El algoritmo de Miller-Rabin determina si un numero es primo o no. Agregar Modular Exponentiation (para m ll) y Modular Multiplication. 2 | 3 | // O(log^3(n)) 4 | bool test(ll n, int a) { 5 | if (n == a) return true; 6 | ll s = 0, d = n-1; 7 | while (d%2 == 0) s++, d /= 2; 8 | ll x = expmod(a, d, n); 9 | if (x == 1 || x+1 == n) return true; 10 | for (int i = 0; i < s-1; i++) { 11 | x = mulmod(x, x, n); 12 | if (x == 1) return false; 13 | if (x+1 == n) return true; 14 | } 15 | return false; 16 | } 17 | 18 | bool is_prime(ll n) { 19 | if (n == 1) return false; 20 | int ar[] = {2, 3, 5, 7, 11, 13, 17, 19, 23}; 21 | for (auto &p : ar) if (!test(n, p)) return false; 22 | return true; 23 | } 24 | -------------------------------------------------------------------------------- /c++/Math/Mobius.cpp: -------------------------------------------------------------------------------- 1 | La funcion mu de Mobius devuelve 0 si n es divisible por algun cuadrado (x^2). 2 | Si n es libre de cuadrados entonces devuelve 1 o -1 si n tiene un numero par o impar de factores primos distintos. 3 | * Calcular Mobius para todos los numeros menores o iguales a MX con Sieve of Eratosthenes. 4 | 5 | const int MX = 1e6; 6 | short mu[MX+1] = {0, 1}; 7 | // O(MX log(log(MX))) 8 | void mobius() { 9 | for (int i = 1; i <= MX; i++) { 10 | if (!mu[i]) continue; 11 | for (int j = i*2; j <= MX; j += i) { 12 | mu[j] -= mu[i]; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /c++/Math/Pollard Rho.cpp: -------------------------------------------------------------------------------- 1 | La función Rho de Pollard calcula un divisor no trivial de n. Agregar Modular Multiplication. 2 | 3 | ll rho(ll n) { 4 | if (!(n&1)) return 2; 5 | ll x = 2, y = 2, d = 1; 6 | ll c = rand() % n + 1; 7 | while (d == 1) { 8 | x = (mulmod(x, x, n) + c) % n; 9 | y = (mulmod(y, y, n) + c) % n; 10 | y = (mulmod(y, y, n) + c) % n; 11 | d = __gcd(abs(x-y), n); 12 | } 13 | return d == n ? rho(n) : d; 14 | } 15 | 16 | * Version optimizada 17 | 18 | ll add(ll a, ll b, ll m) { return (a += b) < m ? a : a-m; } 19 | 20 | ll rho(ll n) { 21 | static ll s[MX]; 22 | while (1) { 23 | ll x = rand()%n, y = x, c = rand()%n; 24 | ll *px = s, *py = s, v = 0, p = 1; 25 | while (1) { 26 | *py++ = y = add(mulmod(y, y, n), c, n); 27 | *py++ = y = add(mulmod(y, y, n), c, n); 28 | if ((x = *px++) == y) break; 29 | ll t = p; 30 | p = mulmod(p, abs(y-x), n); 31 | if (!p) return __gcd(t, n); 32 | if (++v == 26) { 33 | if ((p = __gcd(p, n)) > 1 && p < n) return p; 34 | v = 0; 35 | } 36 | } 37 | if (v && (p = __gcd(p, n)) > 1 && p < n) return p; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /c++/Math/Prime Factorization.cpp: -------------------------------------------------------------------------------- 1 | Tres funciones diferentes que guardan en el map f los pares de la descomposicion en factores primos de n. 2 | 3 | 1.1) Iterando hasta sqrt(n) 4 | // O(sqrt(n)) 5 | void fact(ll n, map &f) { 6 | for (int p = 2; 1ll*p*p <= n; p++) 7 | while (n%p == 0) f[p]++, n /= p; 8 | if (n > 1) f[n]++; 9 | } 10 | 11 | 1.2) Version optimizada. Precalcular los primos <= sqrt(n) para iterarlos en el for. 12 | // O(sqrt(n)/log(sqrt(n))) 13 | 14 | 2.1) Utilizando Pollard Rho y Miller Rabin (agregar funciones). 15 | // O(log(n)^3) aprox 16 | void fact(ll n, map &f) { 17 | if (n == 1) return; 18 | if (is_prime(n)) { f[n]++; return; } 19 | ll q = rho(n); 20 | fact(q, f); fact(n/q, f); 21 | } 22 | 23 | 2.2) Version optimizada. Usar Pollard Rho optimizado y sieve() del metodo 3. 24 | 25 | void fact(ll n, map &f) { 26 | for (auto &p : f) while (n%p.F == 0) { p.S++; n /= p.F; } 27 | if (n <= MX) while (n > 1) { f[prime[n]]++; n /= prime[n]; } 28 | else if (is_prime(n)) f[n]++; 29 | else { ll q = rho(n); fact(q, f); fact(n/q, f); } 30 | } 31 | 32 | 3) Precalculando un divisor primo para cada n (solo para n <= 1e6 aprox). 33 | 34 | const int MX = 1e6; 35 | int prime[MX+1]; 36 | 37 | void sieve() { 38 | for (int i = 2; i <= MX; i++) { 39 | if (prime[i]) continue; 40 | for (int j = i; j <= MX; j += i) { 41 | prime[j] = i; 42 | } 43 | } 44 | } 45 | // O(log(n)) 46 | void fact(int n, map &f) { 47 | while (n > 1) { 48 | f[prime[n]]++; 49 | n /= prime[n]; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /c++/Math/Sieve of Eratosthenes.cpp: -------------------------------------------------------------------------------- 1 | Guarda en primes los numeros primos menores o iguales a MX. Para saber si p es un número primo, hacer: if (!marked[p]). 2 | 3 | const int MX = 1e6; 4 | bool marked[MX+1]; 5 | vector primes; 6 | // O(MX log(log(MX))) 7 | void sieve() { 8 | marked[0] = marked[1] = true; 9 | for (int i = 2; i <= MX; i++) { 10 | if (marked[i]) continue; 11 | primes.pb(i); 12 | for (ll j = 1ll*i*i; j <= MX; j += i) marked[j] = true; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /c++/Math/Simplex integer.cpp: -------------------------------------------------------------------------------- 1 | Resuelve el problema de Linear Integer Programming (LPI). 2 | Agregar Fraction con tipo de dato __int128 y hacer los siguientes ajustes: 3 | 4 | // Cambiar el tipo de dato del Simplex a Fraction 5 | typedef Fraction lf; 6 | 7 | // Agregar constantes 8 | const Fraction ZERO, INF(1e18); 9 | 10 | // Cambiar las siguientes líneas en el Simplex 11 | z = ZERO; // Línea 19 12 | a[x][y] = Fraction(1) / a[x][y]; // Línea 30 13 | if (i != x && a[i][y] != ZERO) { // Línea 32 14 | lf mn = ZERO; // Línea 50 15 | if (a[x][i] < ZERO) { // Línea 56 16 | lf mx = ZERO; // Línea 65 17 | lf mn = INF; // Línea 71 18 | if (a[i][y] > ZERO && b[i] / a[i][y] < mn) // Línea 73 19 | 20 | // Agregar el siguiente método en el Simplex 21 | pair> maximize_int() { 22 | while (true) { 23 | auto sol = maximize(); 24 | bool all_int = true; 25 | for (auto &x : sol.S) all_int &= x.fractional_part() == ZERO; 26 | if (all_int) return sol; 27 | 28 | Fraction nw_b = ZERO; 29 | int id = -1; 30 | for (int i = 0; i < n; i++) { 31 | Fraction fp = b[i].fractional_part(); 32 | if (fp >= nw_b) nw_b = fp, id = i; 33 | } 34 | vector nw_a; 35 | for (auto &x : a[id]) nw_a.pb(-x.fractional_part()); 36 | a.pb(nw_a); 37 | b.pb(-nw_b); 38 | Y.pb(n+m); n++; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /c++/Math/Simplex.cpp: -------------------------------------------------------------------------------- 1 | Maximizar la ecuación x1 + x2 + x3 ... 2 | sujeta a restricciones x1 + x2 <= 2, x2 + x3 <= 5 ... 3 | A: matriz de ecuaciones, contiene los coeficientes de cada variable 4 | B: vector con los coeficientes de las restricciones 5 | C: costos de las variables 6 | 7 | const double EPS = 1e-6; 8 | 9 | typedef double lf; 10 | struct simplex { 11 | vector X, Y; 12 | vector> a; 13 | vector b, c; 14 | lf z; 15 | int n, m; 16 | 17 | simplex(vector> &A, vector &B, vector &C) { 18 | a = A; b = B; c = C; 19 | n = b.size(); m = c.size(); z = 0.0; 20 | X.resize(m); iota(X.begin(), X.end(), 0); 21 | Y.resize(n); iota(Y.begin(), Y.end(), m); 22 | } 23 | 24 | void pivot(int x, int y) { 25 | swap(X[y], Y[x]); 26 | b[x] /= a[x][y]; 27 | for (int i = 0; i < m; i++) { 28 | if (i != y) a[x][i] /= a[x][y]; 29 | } 30 | a[x][y] = 1 / a[x][y]; 31 | for (int i = 0; i < n; i++) { 32 | if (i != x && abs(a[i][y]) > EPS) { 33 | b[i] -= a[i][y] * b[x]; 34 | for (int j = 0; j < m; j++) { 35 | if (j != y) a[i][j] -= a[i][y] * a[x][j]; 36 | } 37 | a[i][y] =- a[i][y] * a[x][y]; 38 | } 39 | } 40 | z += c[y] * b[x]; 41 | for (int i = 0; i < m; i++) { 42 | if (i != y) c[i] -= c[y] * a[x][i]; 43 | } 44 | c[y] =- c[y] * a[x][y]; 45 | } 46 | 47 | pair> maximize() { 48 | while (true) { 49 | int x = -1, y = -1; 50 | lf mn = -EPS; 51 | for (int i = 0; i < n; i++) { 52 | if (b[i] < mn) mn = b[i], x = i; 53 | } 54 | if (x < 0) break; 55 | for (int i = 0; i < m; i++) { 56 | if (a[x][i] < -EPS) { 57 | y = i; 58 | break; 59 | } 60 | } 61 | assert(y >= 0); // no hay solución para Ax <= b 62 | pivot(x, y); 63 | } 64 | while (true) { 65 | lf mx = EPS; 66 | int x = -1, y = -1; 67 | for (int i = 0; i < m; i++) { 68 | if (c[i] > mx) mx = c[i], y = i; 69 | } 70 | if (y < 0) break; 71 | lf mn = 1e200; 72 | for (int i = 0; i < n; i++) { 73 | if (a[i][y] > EPS && b[i] / a[i][y] < mn) 74 | mn = b[i] / a[i][y], x = i; 75 | } 76 | assert(x >= 0); // unbounded 77 | pivot(x, y); 78 | } 79 | vector r(m); 80 | for (int i = 0; i < n; i++) { 81 | if (Y[i] < m) r[Y[i]] = b[i]; 82 | } 83 | return {z, r}; 84 | } 85 | }; 86 | -------------------------------------------------------------------------------- /c++/Math/Ternary Search.cpp: -------------------------------------------------------------------------------- 1 | Retorna el valor máximo de una función f(x) entre [l, r] 2 | 3 | const double eps = 1e-9; 4 | 5 | double ternary_search(double l, double r) { 6 | while (r - l > eps) { // O se pueden hacer unas 100 iteraciones 7 | double m1 = l + (r - l) / 3; 8 | double m2 = r - (r - l) / 3; 9 | double f1 = f(m1); 10 | double f2 = f(m2); 11 | if (f1 < f2) l = m1; 12 | else r = m2; 13 | } 14 | return f(l); 15 | } 16 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Chinese Remainder Theorem.cpp: -------------------------------------------------------------------------------- 1 | Encuentra un x tal que para cada i : x es congruente con A_i mod M_i 2 | Devuelve {x, lcm}, donde x es la solucion con modulo lcm (lcm = LCM(M_0, M_1, ...)). Dado un k : x + k*lcm es solucion tambien. 3 | Si la solucion no existe o la entrada no es valida devuelve {-1, -1} 4 | Agregar Extended Euclides. 5 | 6 | pii crt(vector A, vector M) { 7 | int n = A.size(), ans = A[0], lcm = M[0]; 8 | for (int i = 1; i < n; i++) { 9 | int d = euclid(lcm, M[i]); 10 | if ((A[i] - ans) % d) return {-1, -1}; 11 | int mod = lcm / d * M[i]; 12 | ans = (ans + x * (A[i] - ans) / d % (M[i] / d) * lcm) % mod; 13 | if (ans < 0) ans += mod; 14 | lcm = mod; 15 | } 16 | return {ans, lcm}; 17 | } 18 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Discrete Logarithm.cpp: -------------------------------------------------------------------------------- 1 | Devuelve un entero x tal que a^x = b (mod m) or -1 si no existe tal x. Agregar Modular Exponentiation. 2 | 3 | ll discrete_log(ll a, ll b, ll m) { 4 | a %= m, b %= m; 5 | if (b == 1) return 0; 6 | int cnt = 0; 7 | ll tmp = 1; 8 | for (int g = __gcd(a, m); g != 1; g = __gcd(a, m)) { 9 | if (b%g) return -1; 10 | m /= g, b /= g; 11 | tmp = tmp*a / g % m; 12 | ++cnt; 13 | if (b == tmp) return cnt; 14 | } 15 | map w; 16 | int s = ceil(sqrt(m)); 17 | ll base = b; 18 | for (int i = 0; i < s; i++) { 19 | w[base] = i; 20 | base = base*a % m; 21 | } 22 | base = expmod(a, s, m); 23 | ll key = tmp; 24 | for (int i = 1; i <= s+1; i++) { 25 | key = key*base % m; 26 | if (w.count(key)) return i*s - w[key] + cnt; 27 | } 28 | return -1; 29 | } 30 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Fibonacci mod m.cpp: -------------------------------------------------------------------------------- 1 | Calcula fibonacci(n) % m. 2 | 3 | // O(log(n)) 4 | int fibmod(ll n, int m) { 5 | int a = 0, b = 1, c; 6 | for (int i = 63-__builtin_clzll(n); i >= 0; i--) { 7 | c = a; 8 | a = (1ll*c*(2ll*b-c+m)) % m; 9 | b = (1ll*c*c + 1ll*b*b) % m; 10 | if ((n>>i) & 1) { 11 | c = (a+b) % m; 12 | a = b; b = c; 13 | } 14 | } 15 | return a; 16 | } 17 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Linear Recurrence.cpp: -------------------------------------------------------------------------------- 1 | Calcula el n-esimo termino de una recurrencia lineal (que depende de los k terminos anteriores). 2 | * Llamar init(k) en el main una unica vez si no es necesario inicializar las matrices multiples veces. 3 | Este ejemplo calcula el fibonacci de n como la suma de los k terminos anteriores de la secuencia (En la secuencia comun k es 2). 4 | Agregar Matrix Multiplication con un construcctor vacio. 5 | 6 | matrix F, T; 7 | 8 | void init(int k) { 9 | F = {k, 1}; // primeros k terminos 10 | F[k-1][0] = 1; 11 | T = {k, k}; // fila k-1 = coeficientes: [c_k, c_k-1, ..., c_1] 12 | for (int i = 0; i < k-1; i++) T[i][i+1] = 1; 13 | for (int i = 0; i < k; i++) T[k-1][i] = 1; 14 | } 15 | // O(k^3 log(n)) 16 | int fib(ll n, int k = 2) { 17 | init(k); 18 | matrix ans = pow(T, n+k-1) * F; 19 | return ans[0][0]; 20 | } 21 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Matrix Multiplication.cpp: -------------------------------------------------------------------------------- 1 | Estructura para realizar operaciones de multiplicacion y exponenciacion modular sobre matrices. 2 | 3 | const int mod = 1e9+7; 4 | 5 | struct matrix { 6 | vector> v; 7 | int n, m; 8 | 9 | matrix(int n, int m, bool o = false) : n(n), m(m), v(n, vector(m)) { 10 | if (o) while (n--) v[n][n] = 1; 11 | } 12 | 13 | matrix operator * (const matrix &o) { 14 | matrix ans(n, o.m); 15 | for (int i = 0; i < n; i++) 16 | for (int k = 0; k < m; k++) if (v[i][k]) 17 | for (int j = 0; j < o.m; j++) 18 | ans[i][j] = (1ll*v[i][k]*o.v[k][j] + ans[i][j]) % mod; 19 | return ans; 20 | } 21 | 22 | vector& operator [] (int i) { return v[i]; } 23 | }; 24 | 25 | matrix pow(matrix b, ll e) { 26 | matrix ans(b.n, b.m, true); 27 | while (e) { 28 | if (e&1) ans = ans*b; 29 | b = b*b; 30 | e /= 2; 31 | } 32 | return ans; 33 | } 34 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Modular Exponentiation.cpp: -------------------------------------------------------------------------------- 1 | * Calcula (b^e) % m (e puede ser ll). b debe estar ya con modulo m. 2 | Si m es ll se debe cambiar todo a ll, agregar Modular Multiplication y calcular las multiplicaciones con mulmod(). 3 | // O(log(e)) 4 | int expmod(int b, int e, int m) { 5 | int ans = 1; 6 | while (e) { 7 | if (e&1) ans = (1ll*ans*b) % m; 8 | b = (1ll*b*b) % m; 9 | e /= 2; 10 | } 11 | return ans; 12 | } 13 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Modular Inverse.cpp: -------------------------------------------------------------------------------- 1 | El inverso multiplicativo modular de a % m es un entero b tal que (a*b) % m = 1. Este existe siempre y cuando a y m sean coprimos (gcd(a, m) = 1). 2 | El inverso modular de a se utiliza para calcular (n/a) % m como (n*b) % m. 3 | 4 | * Se puede calcular usando el algoritmo de Euclides extendido. Agregar Extended Euclides. 5 | 6 | // O(log(max(a, m))) 7 | int invmod(int a, int m) { 8 | int d = euclid(a, m); 9 | if (d > 1) return -1; 10 | return (x % m + m) % m; 11 | } 12 | 13 | * Si m es un numero primo, se puede calcular aplicando el pequeño teorema de Fermat. Agregar Modular Exponentiation. 14 | 15 | // O(log(m)) 16 | int invmod(int a, int m) { 17 | return expmod(a, m-2, m); 18 | } 19 | 20 | * Calcular el inverso modulo m para todos los numeros menores o iguales a MX 21 | 22 | const int MX = 1e6; 23 | int inv[MX+1]; 24 | // O(MX) 25 | void invmod(int m) { 26 | inv[1] = 1; 27 | for (int i = 2; i <= MX; i++) 28 | inv[i] = m - ll(m/i) * inv[m%i] % m; 29 | } 30 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Modular Multiplication.cpp: -------------------------------------------------------------------------------- 1 | * Calcula (a*b) % m sin overflow cuando m es ll. 2 | // O(1) 3 | ll mulmod(ll a, ll b, ll m) { 4 | ll r = a*b-(ll)((long double)a*b/m+.5)*m; 5 | return r < 0 ? r+m : r; 6 | } 7 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Pisano Period.cpp: -------------------------------------------------------------------------------- 1 | Calcula el Periodo de Pisano de m, que es el periodo con el cual se repite la Sucesion de Fibonacci modulo m. 2 | Si m es primo el algoritmo funciona (considerable) para m < 10^6. Aregar Modular Exponentiation (sin el modulo) y Lowest Common Multiple (para ll). 3 | 4 | ll period(ll m) { 5 | ll a = 0, b = 1, c, pp = 0; 6 | do { 7 | c = (a+b) % m; 8 | a = b; b = c; pp++; 9 | } while (a != 0 || b != 1); 10 | return pp; 11 | } 12 | 13 | ll pisanoPrime(ll p, int e) { 14 | return expmod(p, e-1) * period(p); 15 | } 16 | 17 | ll pisanoPeriod(ll m) { 18 | ll pp = 1; 19 | for (ll p = 2; p <= m/p; p++) { 20 | if (m%p == 0) { 21 | int e = 0; 22 | while (m%p == 0) e++, m /= p; 23 | pp = lcm(pp, pisanoPrime(p, e)); 24 | } 25 | } 26 | if (m > 1) pp = lcm(pp, period(m)); 27 | return pp; 28 | } 29 | -------------------------------------------------------------------------------- /c++/Modular arithmetic/Primitive Root.cpp: -------------------------------------------------------------------------------- 1 | g es una raíz primitiva módulo n si y solo si para cualquier entero a tal que gcd(a, n) = 1, existe un entero k tal que: g^k = a mod n. 2 | La raíz primitiva módulo n existe si y solo si: n = 1, 2, 4, o n = p^k, o n = 2 * p^k, donde p es un número primo impar. 3 | Agregar Modular Exponentiation. 4 | 5 | // O(ans * log(phi(p)) * log(p)) 6 | int primitive_root(int p) { // Función para cuando p es primo 7 | vector fact; 8 | int phi = p-1, n = phi; // Si p no es primo, calcular Euler totient de p. 9 | for (int i = 2; i*i <= n; ++i) 10 | if (n%i == 0) { 11 | fact.push_back(i); 12 | while (n%i == 0) n /= i; 13 | } 14 | if (n > 1) fact.push_back(n); 15 | 16 | for (int ans = 2; ans <= p; ++ans) { 17 | bool ok = true; 18 | for (int i = 0; i < fact.size() && ok; ++i) 19 | ok &= expmod(ans, phi / fact[i], p) != 1; 20 | if (ok) return ans; 21 | } 22 | return -1; 23 | } 24 | -------------------------------------------------------------------------------- /c++/Network flows/Blossom.cpp: -------------------------------------------------------------------------------- 1 | Halla el máximo match en un grafo general O(E * v ^2) 2 | 3 | struct network { 4 | struct struct_edge { 5 | int v; struct_edge * n; 6 | }; 7 | typedef struct_edge* edge; 8 | 9 | int n; 10 | struct_edge pool[MAXE]; // 2*n*n; 11 | edge top; 12 | vector adj; 13 | queue q; 14 | vector f, base, inq, inb, inp, match; 15 | vector> ed; 16 | 17 | network(int n) : n(n), match(n, -1), adj(n), top(pool), f(n), base(n), 18 | inq(n), inb(n), inp(n), ed(n, vector(n)) {} 19 | 20 | void add_edge(int u, int v) { 21 | if (ed[u][v]) return; 22 | ed[u][v] = 1; 23 | top->v = v, top->n = adj[u], adj[u] = top++; 24 | top->v = u, top->n = adj[v], adj[v] = top++; 25 | } 26 | 27 | int get_lca(int root, int u, int v) { 28 | fill(inp.begin(), inp.end(), 0); 29 | while (1) { 30 | inp[u = base[u]] = 1; 31 | if (u == root) break; 32 | u = f[match[u]]; 33 | } 34 | while (1) { 35 | if (inp[v = base[v]]) return v; 36 | else v = f[match[v]]; 37 | } 38 | } 39 | 40 | void mark(int lca, int u) { 41 | while (base[u] != lca) { 42 | int v = match[u]; 43 | inb[base[u]] = 1; 44 | inb[base[v]] = 1; 45 | u = f[v]; 46 | if (base[u] != lca) f[u] = v; 47 | } 48 | } 49 | 50 | void blossom_contraction(int s, int u, int v) { 51 | int lca = get_lca(s, u, v); 52 | fill(inb.begin(), inb.end(), 0); 53 | mark(lca, u); mark(lca, v); 54 | if (base[u] != lca) f[u] = v; 55 | if (base[v] != lca) f[v] = u; 56 | for (int u = 0; u < n; u++) { 57 | if (inb[base[u]]) { 58 | base[u] = lca; 59 | if (!inq[u]) { 60 | inq[u] = 1; 61 | q.push(u); 62 | } 63 | } 64 | } 65 | } 66 | 67 | int bfs(int s) { 68 | fill(inq.begin(), inq.end(), 0); 69 | fill(f.begin(), f.end(), -1); 70 | for (int i = 0; i < n; i++) base[i] = i; 71 | q = queue(); 72 | q.push(s); 73 | inq[s] = 1; 74 | while (q.size()) { 75 | int u = q.front(); q.pop(); 76 | for (edge e = adj[u]; e; e = e->n) { 77 | int v = e->v; 78 | if (base[u] != base[v] && match[u] != v) { 79 | if ((v == s) || (match[v] != -1 && f[match[v]] != -1)) { 80 | blossom_contraction(s, u, v); 81 | } else if (f[v] == -1) { 82 | f[v] = u; 83 | if (match[v] == -1) return v; 84 | else if (!inq[match[v]]) { 85 | inq[match[v]] = 1; 86 | q.push(match[v]); 87 | } 88 | } 89 | } 90 | } 91 | } 92 | return -1; 93 | } 94 | 95 | int doit(int u) { 96 | if (u == -1) return 0; 97 | int v = f[u]; 98 | doit(match[v]); 99 | match[v] = u; match[u] = v; 100 | return u != -1; 101 | } 102 | 103 | // (i < net.match[i]) => means match 104 | int maximum_matching() { 105 | int ans = 0; 106 | for (int u = 0; u < n; u++) 107 | ans += (match[u] == -1) && doit(bfs(u)); 108 | return ans; 109 | } 110 | }; 111 | -------------------------------------------------------------------------------- /c++/Network flows/Dinic.cpp: -------------------------------------------------------------------------------- 1 | Halla el flujo máximo O(E * V ^ 2) 2 | 3 | struct edge { int v, cap, inv, flow; }; 4 | 5 | struct network { 6 | int n, s, t; 7 | vector lvl; 8 | vector> g; 9 | 10 | network(int n) : n(n), lvl(n), g(n) {} 11 | 12 | void add_edge(int u, int v, int c) { 13 | g[u].pb({v, c, (int)g[v].size(), 0}); 14 | g[v].pb({u, 0, (int)g[u].size()-1, c}); 15 | } 16 | 17 | bool bfs() { 18 | fill(lvl.begin(), lvl.end(), -1); 19 | queue q; 20 | lvl[s] = 0; 21 | for (q.push(s); q.size(); q.pop()) { 22 | int u = q.front(); 23 | for (auto &e : g[u]) { 24 | if (e.cap > 0 && lvl[e.v] == -1) { 25 | lvl[e.v] = lvl[u]+1; 26 | q.push(e.v); 27 | } 28 | } 29 | } 30 | return lvl[t] != -1; 31 | } 32 | 33 | int dfs(int u, int nf) { 34 | if (u == t) return nf; 35 | int res = 0; 36 | for (auto &e : g[u]) { 37 | if (e.cap > 0 && lvl[e.v] == lvl[u]+1) { 38 | int tf = dfs(e.v, min(nf, e.cap)); 39 | res += tf; nf -= tf; e.cap -= tf; 40 | g[e.v][e.inv].cap += tf; 41 | g[e.v][e.inv].flow -= tf; 42 | e.flow += tf; 43 | if (nf == 0) return res; 44 | } 45 | } 46 | if (!res) lvl[u] = -1; 47 | return res; 48 | } 49 | 50 | int max_flow(int so, int si, int res = 0) { 51 | s = so; t = si; 52 | while (bfs()) res += dfs(s, INT_MAX); 53 | return res; 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /c++/Network flows/Hungarian.cpp: -------------------------------------------------------------------------------- 1 | Halla el máximo match en un grafo bipartito con pesos (min cost) O(V ^ 3) 2 | 3 | typedef ll T; 4 | const T inf = 1e18; 5 | 6 | struct hung { 7 | int n, m; 8 | vector u, v; vector p, way; 9 | vector> g; 10 | 11 | hung(int n, int m): 12 | n(n), m(m), g(n+1, vector(m+1, inf-1)), 13 | u(n+1), v(m+1), p(m+1), way(m+1) {} 14 | 15 | void set(int u, int v, T w) { g[u+1][v+1] = w; } 16 | 17 | T assign() { 18 | for (int i = 1; i <= n; ++i) { 19 | int j0 = 0; p[0] = i; 20 | vector minv(m+1, inf); 21 | vector used(m+1, false); 22 | do { 23 | used[j0] = true; 24 | int i0 = p[j0], j1; T delta = inf; 25 | for (int j = 1; j <= m; ++j) if (!used[j]) { 26 | T cur = g[i0][j] - u[i0] - v[j]; 27 | if (cur < minv[j]) minv[j] = cur, way[j] = j0; 28 | if (minv[j] < delta) delta = minv[j], j1 = j; 29 | } 30 | for (int j = 0; j <= m; ++j) 31 | if (used[j]) u[p[j]] += delta, v[j] -= delta; 32 | else minv[j] -= delta; 33 | j0 = j1; 34 | } while (p[j0]); 35 | do { 36 | int j1 = way[j0]; p[j0] = p[j1]; j0 = j1; 37 | } while (j0); 38 | } 39 | return -v[0]; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /c++/Network flows/Maximum Bipartite Matching.cpp: -------------------------------------------------------------------------------- 1 | Halla el maximo match en un grafo bipartito O(|E|*|V|) 2 | 3 | struct mbm { 4 | int l, r; 5 | vector> g; 6 | vector match, vis; 7 | 8 | mbm(int l, int r) : l(l), r(r), g(l) {} 9 | 10 | void add_edge(int l, int r) { 11 | g[l].pb(r); 12 | } 13 | 14 | bool dfs(int u) { 15 | for (auto &v : g[u]) { 16 | if (vis[v]++) continue; 17 | if (match[v] == -1 || dfs(match[v])) { 18 | match[v] = u; 19 | return true; 20 | } 21 | } 22 | return false; 23 | } 24 | 25 | int max_matching() { 26 | int ans = 0; 27 | match.assign(r, -1); 28 | for (int u = 0; u < l; ++u) { 29 | vis.assign(r, 0); 30 | ans += dfs(u); 31 | } 32 | return ans; 33 | } 34 | }; 35 | 36 | Hopcroft Karp: O(E * sqrt(V)) 37 | 38 | const int INF = INT_MAX; 39 | 40 | struct mbm { 41 | vector> g; 42 | vector d, match; 43 | int nil, l, r; 44 | // u -> 0 to l, v -> 0 to r 45 | mbm(int l, int r) : l(l), r(r), nil(l+r), g(l+r), 46 | d(1+l+r, INF), match(l+r, l+r) {} 47 | 48 | void add_edge(int a, int b) { 49 | g[a].pb(l+b); 50 | g[l+b].pb(a); 51 | } 52 | 53 | bool bfs() { 54 | queue q; 55 | for (int u = 0; u < l; u++) { 56 | if (match[u] == nil) { 57 | d[u] = 0; 58 | q.push(u); 59 | } else { 60 | d[u] = INF; 61 | } 62 | } 63 | d[nil] = INF; 64 | while (q.size()) { 65 | int u = q.front(); q.pop(); 66 | if (u == nil) continue; 67 | for (auto v : g[u]) { 68 | if (d[match[v]] == INF) { 69 | d[match[v]] = d[u]+1; 70 | q.push(match[v]); 71 | } 72 | } 73 | } 74 | return d[nil] != INF; 75 | } 76 | 77 | bool dfs(int u) { 78 | if (u == nil) return true; 79 | for (int v : g[u]) { 80 | if (d[match[v]] == d[u]+1 && dfs(match[v])) { 81 | match[v] = u; match[u] = v; 82 | return true; 83 | } 84 | } 85 | d[u] = INF; 86 | return false; 87 | } 88 | 89 | int max_matching() { 90 | int ans = 0; 91 | while (bfs()) { 92 | for (int u = 0; u < l; u++) { 93 | ans += (match[u] == nil && dfs(u)); 94 | } 95 | } 96 | return ans; 97 | } 98 | }; 99 | -------------------------------------------------------------------------------- /c++/Network flows/MinCost MaxFlow.cpp: -------------------------------------------------------------------------------- 1 | Dado un grafo, halla el flujo maximo y el costo minimo entre el source s y el sink t. 2 | 3 | struct edge { 4 | int u, v, cap, flow, cost; 5 | int rem() { return cap - flow; } 6 | }; 7 | 8 | const int inf = 1e9; 9 | const int MX = 405; // Cantidad maxima TOTAL de nodos 10 | vector g[MX]; // Lista de adyacencia 11 | vector e; // Lista de aristas 12 | vector in_queue; // Marca los nodos que estan en cola 13 | vector pre, dist, cap; // Almacena el nodo anterior, la distancia y el flujo de cada nodo 14 | int mxflow, mncost; // Flujo maximo y costo minimo 15 | int N; // Cantidad TOTAL de nodos 16 | 17 | void add_edge(int u, int v, int cap, int cost) { 18 | g[u].pb(e.size()); 19 | e.pb({u, v, cap, 0, cost}); 20 | g[v].pb(e.size()); 21 | e.pb({v, u, 0, 0, -cost}); 22 | } 23 | 24 | void flow(int s, int t) { 25 | mxflow = mncost = 0; 26 | in_queue.assign(N, false); 27 | while (true) { 28 | dist.assign(N, inf); dist[s] = 0; 29 | cap.assign(N, 0); cap[s] = inf; 30 | pre.assign(N, -1); pre[s] = 0; 31 | queue q; q.push(s); 32 | in_queue[s] = true; 33 | 34 | while (q.size()) { 35 | int u = q.front(); q.pop(); 36 | in_queue[u] = false; 37 | for (int &id : g[u]) { 38 | edge &ed = e[id]; 39 | int v = ed.v; 40 | if (ed.rem() && dist[v] > dist[u]+ed.cost) { 41 | dist[v] = dist[u]+ed.cost; 42 | cap[v] = min(cap[u], ed.rem()); 43 | pre[v] = id; 44 | if (!in_queue[v]) { 45 | q.push(v); 46 | in_queue[v] = true; 47 | } 48 | } 49 | } 50 | } 51 | if (pre[t] == -1) break; 52 | mxflow += cap[t]; 53 | mncost += cap[t] * dist[t]; 54 | for (int v = t; v != s; v = e[pre[v]].u) { 55 | e[pre[v]].flow += cap[t]; 56 | e[pre[v]^1].flow -= cap[t]; 57 | } 58 | } 59 | } 60 | 61 | void init() { 62 | e.clear(); 63 | for (int i = 0; i <= N; i++) { 64 | g[i].clear(); 65 | } 66 | } 67 | 68 | // O(V * E * 2 * log(E)) 69 | template 70 | struct mcmf { 71 | struct edge { int u, v, cap, flow; type cost; }; 72 | 73 | int n; 74 | vector ed; 75 | vector> g; 76 | vector p; 77 | vector d, phi; 78 | 79 | mcmf(int n) : n(n), g(n), p(n), d(n), phi(n) {} 80 | 81 | void add_edge(int u, int v, int cap, type cost) { 82 | g[u].pb(ed.size()); 83 | ed.pb({u, v, cap, 0, cost}); 84 | g[v].pb(ed.size()); 85 | ed.pb({v, u, 0, 0, -cost}); 86 | } 87 | 88 | bool dijkstra(int s, int t) { 89 | fill(d.begin(), d.end(), INF); 90 | fill(p.begin(), p.end(), -1); 91 | set> q; 92 | d[s] = 0; 93 | for (q.insert({d[s], s}); q.size();) { 94 | int u = (*q.begin()).second; q.erase(q.begin()); 95 | for (auto v : g[u]) { 96 | auto &e = ed[v]; 97 | type nd = d[e.u]+e.cost+phi[e.u]-phi[e.v]; 98 | if (0 < (e.cap-e.flow) && nd < d[e.v]) { 99 | q.erase({d[e.v], e.v}); 100 | d[e.v] = nd; p[e.v] = v; 101 | q.insert({d[e.v], e.v}); 102 | } 103 | } 104 | } 105 | for (int i = 0; i < n; i++) phi[i] = min(INF, phi[i]+d[i]); 106 | return d[t] != INF; 107 | } 108 | 109 | pair max_flow(int s, int t) { 110 | type mc = 0; 111 | int mf = 0; 112 | fill(phi.begin(), phi.end(), 0); 113 | while (dijkstra(s, t)) { 114 | int flow = INF; 115 | for (int v = p[t]; v != -1; v = p[ed[v].u]) 116 | flow = min(flow, ed[v].cap-ed[v].flow); 117 | for (int v = p[t]; v != -1; v = p[ed[v].u]) { 118 | edge &e1 = ed[v]; 119 | edge &e2 = ed[v^1]; 120 | mc += e1.cost*flow; 121 | e1.flow += flow; 122 | e2.flow -= flow; 123 | } 124 | mf += flow; 125 | } 126 | return {mf, mc}; 127 | } 128 | }; 129 | -------------------------------------------------------------------------------- /c++/Network flows/Stoer Wagner.cpp: -------------------------------------------------------------------------------- 1 | Halla el corte mínimo en un grafo no dirigido y con pesos O(V ^ 3) 2 | 3 | struct stoer_wagner { 4 | int n; 5 | vector> g; 6 | 7 | stoer_wagner(int n) : n(n), g(n, vector(n)) {} 8 | 9 | void add_edge(int a, int b, int w) { 10 | g[a][b] = g[b][a] = w; 11 | } 12 | 13 | pair> min_cut() { 14 | vector used(n); 15 | vector cut, best_cut; 16 | int best_weight = -1; 17 | for (int p = n-1; p >= 0; --p) { 18 | vector w = g[0]; 19 | vector added = used; 20 | int prv, lst = 0; 21 | for (int i = 0; i < p; ++i) { 22 | prv = lst; lst = -1; 23 | for (int j = 1; j < n; ++j) { 24 | if (!added[j] && (lst == -1 || w[j] > w[lst])) lst = j; 25 | } 26 | if (i == p-1) { 27 | for (int j = 0; j < n; j++) 28 | g[prv][j] += g[lst][j]; 29 | for (int j = 0; j < n; j++) 30 | g[j][prv] = g[prv][j]; 31 | used[lst] = true; 32 | cut.pb(lst); 33 | if (best_weight == -1 || w[lst] < best_weight) { 34 | best_cut = cut; 35 | best_weight = w[lst]; 36 | } 37 | } else { 38 | for (int j = 0; j < n; j++) 39 | w[j] += g[lst][j]; 40 | added[lst] = true; 41 | } 42 | } 43 | } 44 | return {best_weight, best_cut}; // best_cut contains all nodes in the same set 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /c++/Network flows/Weighted matching.cpp: -------------------------------------------------------------------------------- 1 | Halla el máximo match con pesos O(V ^ 3) 2 | 3 | typedef int type; 4 | struct matching_weighted { 5 | int l, r; 6 | vector> c; 7 | matching_weighted(int l, int r) : l(l), r(r), c(l, vector(r)) { 8 | assert(l <= r); 9 | } 10 | 11 | void add_edge(int a, int b, type cost) { c[a][b] = cost; } 12 | 13 | type matching() { 14 | vector v(r), d(r); // v: potential 15 | vector ml(l, -1), mr(r, -1); // matching pairs 16 | vector idx(r), prev(r); 17 | iota(idx.begin(), idx.end(), 0); 18 | auto residue = [&](int i, int j) { return c[i][j]-v[j]; }; 19 | for (int f = 0; f < l; ++f) { 20 | for (int j = 0; j < r; ++j) { 21 | d[j] = residue(f, j); 22 | prev[j] = f; 23 | } 24 | type w; 25 | int j, l; 26 | for (int s = 0, t = 0;;) { 27 | if (s == t) { 28 | l = s; 29 | w = d[idx[t++]]; 30 | for (int k = t; k < r; ++k) { 31 | j = idx[k]; 32 | type h = d[j]; 33 | if (h <= w) { 34 | if (h < w) t = s, w = h; 35 | idx[k] = idx[t]; 36 | idx[t++] = j; 37 | } 38 | } 39 | for (int k = s; k < t; ++k) { 40 | j = idx[k]; 41 | if (mr[j] < 0) goto aug; 42 | } 43 | } 44 | int q = idx[s++], i = mr[q]; 45 | for (int k = t; k < r; ++k) { 46 | j = idx[k]; 47 | type h = residue(i, j) - residue(i, q) + w; 48 | if (h < d[j]) { 49 | d[j] = h; 50 | prev[j] = i; 51 | if (h == w) { 52 | if (mr[j] < 0) goto aug; 53 | idx[k] = idx[t]; 54 | idx[t++] = j; 55 | } 56 | } 57 | } 58 | } 59 | aug: 60 | for (int k = 0; k < l; ++k) 61 | v[idx[k]] += d[idx[k]] - w; 62 | int i; 63 | do { 64 | mr[j] = i = prev[j]; 65 | swap(j, ml[i]); 66 | } while (i != f); 67 | } 68 | type opt = 0; 69 | for (int i = 0; i < l; ++i) 70 | opt += c[i][ml[i]]; // (i, ml[i]) is a solution 71 | return opt; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /c++/Strings/Aho Corasick (Trie).cpp: -------------------------------------------------------------------------------- 1 | El trie (o prefix tree) guarda un diccionario de strings como un arbol enraizado. 2 | Aho corasick permite encontrar las ocurrencias de todos los strings del trie en un string s. 3 | 4 | const int alpha = 26; // cantidad de letras del lenguaje 5 | const char L = 'a'; // primera letra del lenguaje 6 | 7 | struct node { 8 | int next[alpha], end; 9 | // int link, exit, cnt; // para aho corasick 10 | int& operator [] (int i) { return next[i]; } 11 | }; 12 | 13 | vector trie = {node()}; 14 | 15 | void add_str(string &s, int id = 1) { 16 | int u = 0; 17 | for (auto ch : s) { 18 | int c = ch-L; 19 | if (!trie[u][c]) { 20 | trie[u][c] = trie.size(); 21 | trie.pb(node()); 22 | } 23 | u = trie[u][c]; 24 | } 25 | trie[u].end = id; // con id > 0 26 | // trie[u].cnt++; // para aho corasick 27 | } 28 | 29 | // aho corasick 30 | void build_ac() { 31 | queue q; q.push(0); 32 | while (q.size()) { 33 | int u = q.front(); q.pop(); 34 | for (int c = 0; c < alpha; ++c) { 35 | int v = trie[u][c]; 36 | if (!v) trie[u][c] = trie[trie[u].link][c]; 37 | else q.push(v); 38 | if (!u || !v) continue; 39 | trie[v].link = trie[trie[u].link][c]; 40 | trie[v].exit = trie[trie[v].link].end ? trie[v].link : trie[trie[v].link].exit; 41 | trie[v].cnt += trie[trie[v].link].cnt; 42 | } 43 | } 44 | } 45 | 46 | vector cnt; // cantidad de ocurrencias en s para cada patron 47 | 48 | void run_ac(string &s) { 49 | int u = 0, sz = s.size(); 50 | for (int i = 0; i < sz; ++i) { 51 | int c = s[i]-L; 52 | while (u && !trie[u][c]) u = trie[u].link; 53 | u = trie[u][c]; 54 | int x = u; 55 | while (x) { 56 | int id = trie[x].end; 57 | if (id) cnt[id-1]++; 58 | x = trie[x].exit; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /c++/Strings/Hashing.cpp: -------------------------------------------------------------------------------- 1 | Convierte el string en un polinomio, en O(n), tal que podemos comparar substrings como valores numericos en O(1). 2 | Primero llamar calc_xpow() (una unica vez) con el largo maximo de los strings dados. 3 | 4 | inline int add(int a, int b, const int &mod) { return a+b >= mod ? a+b-mod : a+b; } 5 | inline int sbt(int a, int b, const int &mod) { return a-b < 0 ? a-b+mod : a-b; } 6 | inline int mul(int a, int b, const int &mod) { return 1ll*a*b % mod; } 7 | 8 | const int X[] = {257, 359}; 9 | const int MOD[] = {(int)1e9+7, (int)1e9+9}; 10 | vector xpow[2]; 11 | 12 | struct hashing { 13 | vector h[2]; 14 | 15 | hashing(string &s) { 16 | int n = s.size(); 17 | for (int j = 0; j < 2; ++j) { 18 | h[j].resize(n+1); 19 | for (int i = 1; i <= n; ++i) { 20 | h[j][i] = add(mul(h[j][i-1], X[j], MOD[j]), s[i-1], MOD[j]); 21 | } 22 | } 23 | } 24 | // Hash del substring en el rango [i, j) 25 | ll value(int l, int r) { 26 | int a = sbt(h[0][r], mul(h[0][l], xpow[0][r-l], MOD[0]), MOD[0]); 27 | int b = sbt(h[1][r], mul(h[1][l], xpow[1][r-l], MOD[1]), MOD[1]); 28 | return (ll(a)<<32) + b; 29 | } 30 | }; 31 | 32 | void calc_xpow(int mxlen) { 33 | for (int j = 0; j < 2; ++j) { 34 | xpow[j].resize(mxlen+1, 1); 35 | for (int i = 1; i <= mxlen; ++i) { 36 | xpow[j][i] = mul(xpow[j][i-1], X[j], MOD[j]); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /c++/Strings/KMP Automaton.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 1e5 + 5, alpha = 26; 2 | const char L = 'A'; 3 | int aut[MAXN][alpha]; // aut[i][j] = a donde vuelvo si estoy en i y pongo una j 4 | 5 | void build(string &s) { 6 | int lps = 0; 7 | aut[0][s[0]-L] = 1; 8 | int n = s.size(); 9 | for (int i = 1; i < n+1; i++) { 10 | for (int j = 0; j < alpha; j++) aut[i][j] = aut[lps][j]; 11 | if (i < n) { 12 | aut[i][s[i]-L] = i + 1; 13 | lps = aut[lps][s[i]-L]; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /c++/Strings/KMP.cpp: -------------------------------------------------------------------------------- 1 | Cuenta las ocurrencias del string p en el string s. Agregar Prefix Function. 2 | 3 | // O(n+m) 4 | int kmp(string &s, string &p) { 5 | int n = s.size(), m = p.size(), cnt = 0; 6 | vector pf = prefix_function(p); 7 | for (int i = 0, j = 0; i < n; i++) { 8 | while (j && s[i] != p[j]) j = pf[j-1]; 9 | if (s[i] == p[j]) j++; 10 | if (j == m) { 11 | cnt++; 12 | j = pf[j-1]; 13 | } 14 | } 15 | return cnt; 16 | } 17 | -------------------------------------------------------------------------------- /c++/Strings/Manacher.cpp: -------------------------------------------------------------------------------- 1 | Devuelve un vector p donde, para cada i, p[i] es igual al largo del palindromo mas largo con centro en i. 2 | 3 | string parse(string &s) { 4 | string t = "%"; 5 | for (auto &c : s) t.pb('#'), t.pb(c); 6 | t += "#$"; 7 | return t; 8 | } 9 | 10 | vector manacher(string &s) { 11 | string t = parse(s); 12 | int n = t.size(), c = 0, r = 0; 13 | vector p(n, 0); 14 | for (int i = 1; i < n-1; i++) { 15 | int j = c - (i-c) ; 16 | if (r > i) p[i] = min(r-i, p[j]); 17 | while (t[i+1+p[i]] == t[i-1-p[i]]) 18 | p[i]++; 19 | if (i+p[i] > r) { 20 | c = i; 21 | r = i+p[i]; 22 | } 23 | } 24 | return p; 25 | // si p[i] > 0 entonces, s[l, r) es palíndromo 26 | // donde l = (i-1-p[i])/2 y r = l+p[i]; 27 | } 28 | -------------------------------------------------------------------------------- /c++/Strings/Minimum Expression.cpp: -------------------------------------------------------------------------------- 1 | Dado un string s devuelve el indice donde comienza la rotación lexicograficamente menor de s. 2 | 3 | // O(n) 4 | int minimum_expression(string s) { 5 | s = s+s; // si no se concatena devuelve el indice del sufijo menor 6 | int len = s.size(), i = 0, j = 1, k = 0; 7 | while (i+k < len && j+k < len) { 8 | if (s[i+k] == s[j+k]) k++; 9 | else if (s[i+k] > s[j+k]) i = i+k+1, k = 0; // cambiar por < para maximum 10 | else j = j+k+1, k = 0; 11 | if (i == j) j++; 12 | } 13 | return min(i, j); 14 | } 15 | -------------------------------------------------------------------------------- /c++/Strings/Palindromic tree.cpp: -------------------------------------------------------------------------------- 1 | const int alfa = 26; 2 | const char L = 'a'; 3 | 4 | struct node { 5 | int next[alfa], link, len; 6 | ll cnt; 7 | node(int x, int l = 0, ll c = 1): len(x), link(l), cnt(c) { 8 | memset(next, 0, sizeof next); 9 | } 10 | int& operator [] (int i) { return next[i]; } 11 | }; 12 | 13 | struct palindromic_tree { 14 | vector tree; 15 | string s; 16 | int n; 17 | int last; 18 | palindromic_tree(string t = "") { 19 | n = last = 0; 20 | tree.pb(node(-1)); 21 | tree.pb(node(0)); 22 | for (auto &c: t)add_char(c); 23 | } 24 | 25 | int getlink(int p) { 26 | while (s[n - tree[p].len - 1] != s[n])p = tree[p].link; 27 | return p; 28 | } 29 | 30 | void add_char(char ch) { 31 | s.pb(ch); 32 | int p = getlink(last), c = ch - L; 33 | if (!tree[p][c]) { 34 | int link = getlink(tree[p].link); 35 | link = max(1, tree[link][c]); 36 | tree[p][c] = SZ(tree); 37 | tree.pb(node(tree[p].len + 2, link, 0)); 38 | } 39 | last = tree[p][c]; 40 | tree[last].cnt++; 41 | n++; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /c++/Strings/Prefix Function.cpp: -------------------------------------------------------------------------------- 1 | Dado un string s retorna un vector pf donde pf[i] es el largo del prefijo propio mas largo que tambien es sufijo de s[0] hasta s[i]. 2 | 3 | // O(n) 4 | vector prefix_function(string &s) { 5 | int n = s.size(); 6 | vector pf(n); 7 | pf[0] = 0; 8 | for (int i = 1, j = 0; i < n; i++) { 9 | while (j && s[i] != s[j]) j = pf[j-1]; 10 | if (s[i] == s[j]) j++; 11 | pf[i] = j; 12 | } 13 | return pf; 14 | } 15 | -------------------------------------------------------------------------------- /c++/Strings/Suffix Array.cpp: -------------------------------------------------------------------------------- 1 | const int MAXL = 300; 2 | 3 | struct suffixArray { 4 | string s; 5 | int n, MX; 6 | vector ra, tra, sa, tsa, lcp; 7 | 8 | suffixArray(string &_s) { 9 | s = _s+"$"; 10 | n = s.size(); 11 | MX = max(MAXL, n)+2; 12 | ra = tra = sa = tsa = lcp = vector(n); 13 | build(); 14 | } 15 | 16 | void radix_sort(int k) { 17 | vector cnt(MX, 0); 18 | for (int i = 0; i < n; i++) 19 | cnt[(i+k < n) ? ra[i+k]+1 : 1]++; 20 | for (int i = 1; i < MX; i++) 21 | cnt[i] += cnt[i-1]; 22 | for (int i = 0; i < n; i++) 23 | tsa[cnt[(sa[i]+k < n) ? ra[sa[i]+k] : 0]++] = sa[i]; 24 | sa = tsa; 25 | } 26 | 27 | void build() { 28 | for (int i = 0; i < n; i++) 29 | ra[i] = s[i], sa[i] = i; 30 | for (int k = 1, r; k < n; k <<= 1) { 31 | radix_sort(k); 32 | radix_sort(0); 33 | tra[sa[0]] = r = 0; 34 | for (int i = 1; i < n; i++) { 35 | if (ra[sa[i]] != ra[sa[i-1]] || ra[sa[i]+k] != ra[sa[i-1]+k]) ++r; 36 | tra[sa[i]] = r; 37 | } 38 | ra = tra; 39 | if (ra[sa[n-1]] == n-1) break; 40 | } 41 | } 42 | 43 | int& operator [] (int i) { return sa[i]; } 44 | 45 | void build_lcp() { 46 | lcp[0] = 0; 47 | for (int i = 0, k = 0; i < n; i++) { 48 | if (!ra[i]) continue; 49 | while (s[i+k] == s[sa[ra[i]-1]+k]) k++; 50 | lcp[ra[i]] = k; 51 | if (k) k--; 52 | } 53 | } 54 | // Longest Common Substring: construir el suffixArray s = s1 + "#" + s2 + "$" y m = s2.size() 55 | pii lcs() { 56 | int mx = -1, ind = -1; 57 | for (int i = 1; i < n; i++) { 58 | if (((sa[i] < n-m-1) != (sa[i-1] < n-m-1)) && mx < lcp[i]) { 59 | mx = lcp[i]; ind = i; 60 | } 61 | } 62 | return {mx, ind}; 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /c++/Strings/Suffix Automaton.cpp: -------------------------------------------------------------------------------- 1 | struct suffixAutomaton { 2 | struct node { 3 | int len, link; bool end; 4 | map next; 5 | int fpos, cnt; ll out; 6 | }; 7 | 8 | vector sa; 9 | int last; 10 | ll substrs = 0; 11 | 12 | suffixAutomaton() {} 13 | suffixAutomaton(string &s) { 14 | sa.reserve(s.size()*2); 15 | last = add_node(); 16 | sa[0].link = -1; 17 | for (char &c : s) add_char(c); 18 | for (int p = last; p; p = sa[p].link) sa[p].end = 1; 19 | } 20 | 21 | int add_node() { sa.pb({}); return sa.size()-1; } 22 | 23 | void add_char(char c) { 24 | int u = add_node(), p = last; 25 | sa[u].len = sa[last].len + 1; 26 | sa[u].fpos = sa[u].len - 1; 27 | while (p != -1 && !sa[p].next.count(c)) { 28 | sa[p].next[c] = u; 29 | substrs += p != 0 ? sa[p].len - sa[sa[p].link].len : 1; 30 | p = sa[p].link; 31 | } 32 | if (p != -1) { 33 | int q = sa[p].next[c]; 34 | if (sa[p].len + 1 != sa[q].len) { 35 | int clone = add_node(); 36 | sa[clone] = sa[q]; 37 | sa[clone].len = sa[p].len + 1; 38 | sa[q].link = sa[u].link = clone; 39 | while (p != -1 && sa[p].next[c] == q) { 40 | sa[p].next[c] = clone; 41 | p = sa[p].link; 42 | } 43 | } else sa[u].link = q; 44 | } 45 | last = u; 46 | } 47 | 48 | void run(string &s) { 49 | int u = 0; 50 | for (int i = 0; i < s.size(); ++i) { 51 | while (u && !sa[u].next.count(s[i])) u = sa[u].link; 52 | if (sa[u].next.count(s[i])) u = sa[u].next[s[i]]; 53 | } 54 | } 55 | 56 | int match_str(string &s) { 57 | int u = 0, n = s.size(); 58 | for (int i = 0; i < n; ++i) { 59 | if (!sa[u].next.count(s[i])) return 0; 60 | u = sa[u].next[s[i]]; 61 | } 62 | return count_occ(u); 63 | } 64 | 65 | int count_occ(int u) { 66 | if (sa[u].cnt != 0) return sa[u].cnt; 67 | sa[u].cnt = sa[u].end; 68 | for (auto &v : sa[u].next) 69 | sa[u].cnt += count_occ(v.S); 70 | return sa[u].cnt; 71 | } 72 | 73 | ll count_paths(int u) { 74 | if (sa[u].out != 0) return sa[u].out; 75 | for (auto &v : sa[u].next) 76 | sa[u].out += count_paths(v.S) + 1; 77 | return sa[u].out; 78 | } 79 | 80 | node& operator[](int i) { return sa[i]; } 81 | }; 82 | -------------------------------------------------------------------------------- /c++/Strings/Z Function.cpp: -------------------------------------------------------------------------------- 1 | Dado un string s retorna un vector z donde z[i] es igual al mayor numero de caracteres desde s[i] que coinciden con los caracteres desde s[0] 2 | 3 | // O(n) 4 | vector z_function(string &s) { 5 | int n = s.size(); 6 | vector z(n); 7 | for (int i = 1, x = 0, y = 0; i < n; i++) { 8 | z[i] = max(0, min(z[i-x], y-i+1)); 9 | while (i+z[i] < n && s[z[i]] == s[i+z[i]]) { 10 | x = i, y = i+z[i], z[i]++; 11 | } 12 | } 13 | return z; 14 | } 15 | -------------------------------------------------------------------------------- /c++/Utilities/Bits Manipulation.cpp: -------------------------------------------------------------------------------- 1 | * Operaciones a nivel de bits. Si n es ll usar 1ll<< en los corrimientos. 2 | 3 | x & 1 -> Verifica si x es impar 4 | x & (1< Verifica si el i-esimo bit esta encendido 5 | x = x | (1< Enciende el i-esimo bit 6 | x = x & ~(1< Apaga el i-esimo bit 7 | x = x ^ (1< Invierte el i-esimo bit 8 | x = ~x -> Invierte todos los bits 9 | x & -x -> Devuelve el bit encendido mas a la derecha (potencia de 2, no el indice) 10 | ~x & (x+1) -> Devuelve el bit apagado mas a la derecha (potencia de 2, no el indice) 11 | x = x | (x+1) -> Enciende el bit apagado mas a la derecha 12 | x = x & (x-1) -> Apaga el bit encendido mas a la derecha 13 | x = x & ~y -> Apaga en x los bits encendidos de y 14 | 15 | * Funciones del compilador gcc. Si n es ll agregar el sufijo ll, por ej: __builtin_clzll(n). 16 | 17 | __builtin_clz(x) -> Cantidad de bits apagados por la izquierda 18 | __builtin_ctz(x) -> Cantidad de bits apagados por la derecha. Indice del bit encendido mas a la derecha 19 | __builtin_popcount(x) -> Cantida de bits encendidos 20 | 21 | * Logaritmo en base 2 (entero). Indice del bit encendido mas a la izquierda. Si x es ll usar 63 y clzll(x). 22 | // O(1) 23 | int lg2(const int &x) { return 31-__builtin_clz(x); } 24 | 25 | * Itera, con indices, los bits encendidos de una mascara. 26 | // O(#bits_encendidos) 27 | for (int x = mask; x; x &= x-1) { 28 | int i = __builtin_ctz(x); 29 | 30 | } 31 | 32 | * Itera todas las submascaras de una mascara. (Iterar todas las submascaras de todas las mascaras es O(3^n)). 33 | // O(2^(#bits_encendidos)) 34 | for (int sub = mask; sub; sub = (sub-1)&mask) { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /c++/Utilities/Random Integer.cpp: -------------------------------------------------------------------------------- 1 | Genera un numero entero aleatorio en el rango [a, b]. Para ll usar "mt19937_64" y cambiar todo a ll. 2 | 3 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 4 | int rand(int a, int b) { return uniform_int_distribution(a, b)(rng); } 5 | -------------------------------------------------------------------------------- /c++/Utilities/Split String.cpp: -------------------------------------------------------------------------------- 1 | Divide el string s por cada espacio ' ' y devuelve un vector<> con los substrings resultantes. 2 | Para dividir el string por un caracter especifico, agregar el parametro c y cambiar el while. 3 | 4 | vector split(const string &s/*, char c*/) { 5 | vector v; 6 | stringstream ss(s); 7 | string sub; 8 | while (ss >> sub) v.pb(sub); 9 | // while (getline(ss, sub, c)) v.pb(sub); 10 | return v; 11 | } 12 | -------------------------------------------------------------------------------- /c++/Utilities/Template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define fastIO ios::sync_with_stdio(0), cin.tie(0) 4 | #define endl '\n' 5 | #define pb push_back 6 | typedef long long ll; 7 | typedef pair pii; 8 | 9 | int main() { 10 | fastIO; 11 | // Tu código... 12 | int a, b; 13 | cin >> a >> b; 14 | double c = a + b; 15 | // Para imprimir con 6 decimales 16 | // cout << fixed << setprecision(6); 17 | cout << c << endl; 18 | } 19 | -------------------------------------------------------------------------------- /c++/Utilities/scanf and printf.cpp: -------------------------------------------------------------------------------- 1 | * Lectura segun el tipo de dato (Se usan las mismas para imprimir): 2 | 3 | scanf("%d", &value); // int 4 | scanf("%ld", &value); // long y long int 5 | scanf("%c", &value); // char 6 | scanf("%f", &value); // float 7 | scanf("%lf", &value); // double 8 | scanf("%s", &value); // char* 9 | scanf("%lld", &value); // long long int 10 | scanf("%x", &value); // int hexadecimal 11 | scanf("%o", &value); // int octal 12 | 13 | * Impresion de punto flotante con d decimales, ejemplo 6 decimales: 14 | 15 | printf("%.6lf", value); 16 | -------------------------------------------------------------------------------- /c++/Values sequences and results/ASCII Table.tex: -------------------------------------------------------------------------------- 1 | Caracteres ASCII con sus respectivos valores numéricos. 2 | 3 | \begin{tabbing} 4 | \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \= \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \\ 5 | 0 \> NUL \> 16 \> DLE \\ 6 | 1 \> SOH \> 17 \> DC1 \\ 7 | 2 \> STX \> 18 \> DC2 \\ 8 | 3 \> ETX \> 19 \> DC3 \\ 9 | 4 \> EOT \> 20 \> DC4 \\ 10 | 5 \> ENQ \> 21 \> NAK \\ 11 | 6 \> ACK \> 22 \> SYN \\ 12 | 7 \> BEL \> 23 \> ETB \\ 13 | 8 \> BS \> 24 \> CAN \\ 14 | 9 \> TAB \> 25 \> EM \\ 15 | 10 \> LF \> 26 \> SUB \\ 16 | 11 \> VT \> 27 \> ESC \\ 17 | 12 \> FF \> 28 \> FS \\ 18 | 13 \> CR \> 29 \> GS \\ 19 | 14 \> SO \> 30 \> RS \\ 20 | 15 \> SI \> 31 \> US \\ 21 | \end{tabbing} 22 | 23 | \begin{tabbing} 24 | \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \= \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \\ 25 | 32 \> (space) \> 48 \> 0 \\ 26 | 33 \> ! \> 49 \> 1 \\ 27 | 34 \> " \> 50 \> 2 \\ 28 | 35 \> \# \> 51 \> 3 \\ 29 | 36 \> \$ \> 52 \> 4 \\ 30 | 37 \> \% \> 53 \> 5 \\ 31 | 38 \> \& \> 54 \> 6 \\ 32 | 39 \> ' \> 55 \> 7 \\ 33 | 40 \> ( \> 56 \> 8 \\ 34 | 41 \> ) \> 57 \> 9 \\ 35 | 42 \> * \> 58 \> : \\ 36 | 43 \> + \> 59 \> ; \\ 37 | 44 \> , \> 60 \> < \\ 38 | 45 \> - \> 61 \> = \\ 39 | 46 \> . \> 62 \> > \\ 40 | 47 \> / \> 63 \> ? \\ 41 | \end{tabbing} 42 | 43 | \begin{tabbing} 44 | \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \= \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \\ 45 | 64 \> @ \> 80 \> P \\ 46 | 65 \> A \> 81 \> Q \\ 47 | 66 \> B \> 82 \> R \\ 48 | 67 \> C \> 83 \> S \\ 49 | 68 \> D \> 84 \> T \\ 50 | 69 \> E \> 85 \> U \\ 51 | 70 \> F \> 86 \> V \\ 52 | 71 \> G \> 87 \> W \\ 53 | 72 \> H \> 88 \> X \\ 54 | 73 \> I \> 89 \> Y \\ 55 | 74 \> J \> 90 \> Z \\ 56 | 75 \> K \> 91 \> [ \\ 57 | 76 \> L \> 92 \> \textbackslash \\ 58 | 77 \> M \> 93 \> ] \\ 59 | 78 \> N \> 94 \> \textasciicircum \\ 60 | 79 \> O \> 95 \> \_ \\ 61 | \end{tabbing} 62 | 63 | \begin{tabbing} 64 | \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \= \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \\ 65 | 96 \> ` \> 112 \> p \\ 66 | 97 \> a \> 113 \> q \\ 67 | 98 \> b \> 114 \> r \\ 68 | 99 \> c \> 115 \> s \\ 69 | 100 \> d \> 116 \> t \\ 70 | 101 \> e \> 117 \> u \\ 71 | 102 \> f \> 118 \> v \\ 72 | 103 \> g \> 119 \> w \\ 73 | 104 \> h \> 120 \> x \\ 74 | 105 \> i \> 121 \> y \\ 75 | 106 \> j \> 122 \> z \\ 76 | 107 \> k \> 123 \> \{ \\ 77 | 108 \> l \> 124 \> \textbar \\ 78 | 109 \> m \> 125 \> \} \\ 79 | 110 \> n \> 126 \> \textasciitilde \\ 80 | 111 \> o \> 127 \> \\ 81 | \end{tabbing} 82 | -------------------------------------------------------------------------------- /c++/Values sequences and results/Sequences.tex: -------------------------------------------------------------------------------- 1 | Listado de secuencias mas comunes y como hallarlas. 2 | 3 | \begin{center} 4 | \tablefirsthead{} 5 | \tabletail{ 6 | \midrule 7 | \multicolumn{2}{r}{{Continúa en la siguiente columna}} \\} 8 | \tablelasttail{} 9 | {\renewcommand{\arraystretch}{1.4} 10 | \begin{supertabular}{|p{1.8cm}|p{8.6cm}|} 11 | 12 | \hline 13 | 14 | \multirow{2}{2cm}{Estrellas octangulares} 15 | & 0, 1, 14, 51, 124, 245, 426, 679, 1016, 1449, 1990, 2651, ... 16 | \\ \cline{2-2} 17 | & $f(n) = n*(2*n^{2} - 1)$. 18 | \\ \hline 19 | 20 | \multirow{2}{2cm} 21 | {Euler totient} 22 | & 1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6,... 23 | \\ \cline{2-2} 24 | & $f(n) = $ Cantidad de números naturales $\leq n$ coprimos con n. 25 | \\ \hline 26 | 27 | \multirow{2}{2cm}{Números de Bell} 28 | & 1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, ... 29 | \\ \cline{2-2} 30 | & Se inicia una matriz triangular con f[0][0] = f[1][0] = 1. La suma de estos dos se guarda en f[1][1] y se traslada a f[2][0]. Ahora se suman f[1][0] con f[2][0] y se guarda en f[2][1]. Luego se suman f[1][1] con f[2][1] y se guarda en f[2][2] trasladandose a f[3][0] y así sucesivamente. Los valores de la primera columna contienen la respuesta. 31 | \\ \hline 32 | 33 | \multirow{2}{2cm} 34 | {Números de Catalán} 35 | & 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, ... 36 | \\ \cline{2-2} 37 | & $f(n)=\displaystyle\frac{(2n)!}{(n + 1)! n!}$ 38 | 39 | \\ \hline 40 | 41 | \multirow{2}{2cm}{Números de Fermat} 42 | & 3, 5, 17, 257, 65537, 4294967297, 18446744073709551617, ... 43 | \\ \cline{2-2} 44 | & $f(n) = 2^{(\displaystyle2^{\textstyle n})} + 1$ 45 | \\ \hline 46 | 47 | \multirow{2}{2cm} 48 | {Números de Fibonacci} 49 | & 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ... 50 | \\ \cline{2-2} 51 | & $f(0) = 0$; $f(1) = 1$; $f(n) = f(n-1) + f(n-2)$ para $n>1$ \\ \hline 52 | 53 | \multirow{2}{2cm} 54 | {Números de Lucas} 55 | & 2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199, 322, ... 56 | \\ \cline{2-2} 57 | & $f(0) = 2$; $f(1) = 1$; $f(n) = f(n-1) + f(n-2)$ para $n>1$ 58 | \\ \hline 59 | 60 | \multirow{2}{2cm}{Números de Pell} 61 | & 0, 1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, ... 62 | \\ \cline{2-2} 63 | & $f(0) = 0; f(1) = 1; f(n) = 2f(n-1) + f(n-2)$ para $n>1$ 64 | \\ \hline 65 | 66 | \multirow{2}{2cm} 67 | {Números de Tribonacci} 68 | & 0, 0, 1, 1, 2, 4, 7, 13, 24, 44, 81, 149, 274, 504, ... 69 | \\ \cline{2-2} 70 | & $f(0)=f(1)=0; f(2)=1; f(n) = f(n-1) + f(n-2) + f(n-3)$ para $n>2$ 71 | \\ \hline 72 | 73 | \multirow{2}{2cm}{Números factoriales} 74 | & 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, ... 75 | \\ \cline{2-2} 76 | &$ f(0) = 1; f(n) = \displaystyle\prod_{\textstyle k=1}^{\textstyle n}k$ para $n>0$. 77 | 78 | \\ \hline 79 | 80 | \multirow{2}{2cm}{Números piramidales cuadrados} 81 | & 0, 1, 5, 14, 30, 55, 91, 140, 204, 285, 385, 506, 650, ... 82 | \\ \cline{2-2} 83 | & $f(n) = \displaystyle\frac{n*(n+1)*(2*n+1)}{6}$ 84 | 85 | \\ \hline 86 | 87 | \multirow{2}{2cm}{Números primos de Mersenne} 88 | & 3, 7, 31, 127, 8191, 131071, 524287, 2147483647, ... 89 | \\ \cline{2-2} 90 | & $f(n) = 2^{p(n)} - 1$ donde $p$ representa valores primos iniciando en $p(0)=2$. 91 | \\ \hline 92 | 93 | 94 | \multirow{2}{2cm}{Números tetraedrales} 95 | & 1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 286, 364, 455, ... 96 | \\ \cline{2-2} 97 | & $f(n) = \displaystyle\frac{n*(n+1)*(n+2)}{6}$ 98 | 99 | \\ \hline 100 | 101 | \multirow{2}{2cm}{Números triangulares} 102 | & 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, ... 103 | \\ \cline{2-2} 104 | & $f(n) = \displaystyle\frac{n(n+1)}{2}$ 105 | 106 | \\ \hline 107 | 108 | \multirow{2}{2cm}{OEIS A000127} 109 | & 1, 2, 4, 8, 16, 31, 57, 99, 163, 256, 386, 562, ... 110 | \\ \cline{2-2} 111 | & $f(n) = \displaystyle\frac{(n^{4}-6n^{3}+23n^{2}-18{n}+24)}{24}$. 112 | 113 | \\ \hline 114 | 115 | \multirow{2}{2cm}{Secuencia de Narayana} 116 | & 1, 1, 1, 2, 3, 4, 6, 9, 13, 19, 28, 41, 60, 88, 129, ... 117 | \\ \cline{2-2} 118 | & $f(0) = f(1) = f(2) = 1; f(n) = f(n-1) + f(n-3)$ para todo $n>2$. 119 | \\ \hline 120 | 121 | \multirow{2}{2cm} 122 | {Secuencia de Silvestre} 123 | & 2, 3, 7, 43, 1807, 3263443, 10650056950807, ... 124 | \\ \cline{2-2} 125 | & $f(0) = 2; f(n+1) = f(n)^2 - f(n) + 1$ 126 | \\ \hline 127 | 128 | \multirow{2}{2cm}{Secuencia de vendedor perezoso} 129 | & 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, 56, 67, 79, 92, 106, ... 130 | \\ \cline{2-2} 131 | & Equivale al triangular(n) + 1. Máxima número de piezas que se pueden formar al hacer n cortes a un disco. 132 | 133 | $f(n) = \displaystyle\frac{n(n+1)}{2} + 1$ 134 | 135 | \\ \hline 136 | 137 | \multirow{2}{2cm}{Suma de los divisores de un número} 138 | & 1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, ... 139 | \\ \cline{2-2} 140 | &Para todo $n>1$ cuya descomposición en factores primos es $n=\displaystyle p_{1}^{\textstyle a_{1}}\displaystyle p_{2}^{\textstyle a_{2}}...\displaystyle p_{k}^{\textstyle a_{k}}$ se tiene que: 141 | 142 | $f(n) = \displaystyle\frac{p_{1}^{a_{1} + 1} - 1}{p_{1} - 1} * \frac{p_{2}^{a_{2} + 1} - 1}{p_{2} - 1} * ... * \frac{p_{k}^{a_{k} + 1} - 1}{p_{k} - 1}$ 143 | 144 | \\ \hline 145 | \end{supertabular} 146 | } 147 | \end{center} 148 | -------------------------------------------------------------------------------- /c++/Values sequences and results/Time Complexities.tex: -------------------------------------------------------------------------------- 1 | Aproximación del mayor número n de datos que pueden procesarse para cada una de las complejidades algoritmicas. Tomar esta tabla solo como referencia. 2 | 3 | \begin{tabbing} 4 | \textbf{Complexity}\hspace{4cm} \= \textbf{n}\hspace{3cm} \\ 5 | $O(n!)$ \> 11\\ 6 | $O(n^{5})$ \> 50\\ 7 | $O(2^{n}*n^{2})$ \> 18\\ 8 | $O(2^{n}*n)$ \> 22\\ 9 | $O(n^{4})$ \> 100\\ 10 | $O(n^{3})$ \> 500\\ 11 | $O(n^{2}\log_{2}n)$ \> 1.000\\ 12 | $O(n^{2})$ \> 10.000\\ 13 | $O(n\log_{2}n)$ \> $10^{6}$\\ 14 | $O(n)$ \> $10^{8}$\\ 15 | $O(\sqrt{n})$ \> $10^{16}$\\ 16 | $O(\log_{2}n)$ \> -\\ 17 | $O(1)$ \> -\\ 18 | \end{tabbing} 19 | -------------------------------------------------------------------------------- /java [outdated]/Data Structures/Disjoint Set.java: -------------------------------------------------------------------------------- 1 | Estructura de datos para modelar una colección de conjuntos disyuntos. 2 | Permite determinar de manera eficiente a que conjunto pertenece un elemento, 3 | si dos elementos se encuentran en un mismo conjunto y unir dos conjuntos disyuntos en un uno. 4 | 5 | static class dsu { 6 | int[] par, sz; 7 | int size; // Cantidad de conjuntos 8 | 9 | dsu(int n) { 10 | size = n; 11 | par = new int[n]; 12 | sz = new int[n]; 13 | for (int i = 0; i < n; i++) { 14 | par[i] = i; 15 | sz[i] = 1; 16 | } 17 | } 18 | // Busca el nodo representativo del conjunto de u 19 | int find(int u) { 20 | return par[u] == u ? u : (par[u] = find(par[u])); 21 | } 22 | // Une los conjuntos de u y v 23 | void unite(int u, int v) { 24 | if ((u = find(u)) == (v = find(v))) return; 25 | if (sz[u] > sz[v]) { 26 | int aux = u; 27 | u = v; 28 | v = aux; 29 | } 30 | par[u] = v; 31 | sz[v] += sz[u]; 32 | size--; 33 | } 34 | // Retorna la cantidad de elementos del conjunto de u 35 | int count(int u) { 36 | return sz[find(u)]; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /java [outdated]/Data Structures/Fenwick Tree.java: -------------------------------------------------------------------------------- 1 | Estructura de datos que permite procesar consultas por rangos y actualizaciones individuales sobre un arreglo. 2 | 3 | static int N = 100000; 4 | static int bit[] = new int[N+1]; 5 | 6 | void add(int k, int val) { 7 | for (; k <= N; k += k&-k) bit[k] += val; 8 | } 9 | 10 | int rsq(int k) { 11 | int sum = 0; 12 | for (; k >= 1; k -= k&-k) sum += bit[k]; 13 | return sum; 14 | } 15 | 16 | int rsq(int i, int j) { return rsq(j) - rsq(i-1); } 17 | 18 | int lower_find(int val) { // last value < or <= to val 19 | int idx = 0; 20 | for (int i = 31-Integer.numberOfLeadingZeros(N); i >= 0; --i) { 21 | int nidx = idx | (1 << i); 22 | if (nidx <= N && bit[nidx] <= val) { // change <= to < 23 | val -= bit[nidx]; 24 | idx = nidx; 25 | } 26 | } 27 | return idx; 28 | } 29 | -------------------------------------------------------------------------------- /java [outdated]/Data Structures/RMQ.java: -------------------------------------------------------------------------------- 1 | Estructura de datos que permite procesar consultas por rangos y actualizaciones individuales sobre un arreglo. 2 | Recibe como parametro en el constructor un arreglo de valores. 3 | IMPORTANTE: Para para procesar actualizaciones por rangos se deben descomentar los lineas de Lazy Propagation. 4 | 5 | static class SegmentTree { 6 | int[] st; // , lazy; 7 | int n, neutro = 1 << 30; 8 | 9 | SegmentTree(int[] arr) { 10 | n = arr.length; 11 | st = new int[n << 2]; 12 | // lazy = new int[n << 2]; 13 | // Arrays.fill(lazy, neutro); 14 | build(1, 0, n - 1, arr); 15 | } 16 | 17 | int query(int i, int j) { return query(1, 0, n - 1, i, j); } 18 | void update(int i, int j, int val) { update(1, 0, n - 1, i, j, val); } 19 | 20 | int left(int p) { return p << 1; } 21 | int right(int p) { return (p << 1) | 1; } 22 | 23 | void build(int p, int L, int R, int[] arr) { 24 | if (L == R) st[p] = arr[L]; 25 | else { 26 | int m = (L+R)/2, l = left(p), r = right(p); 27 | build(l, L, m, arr); 28 | build(r, m + 1, R, arr); 29 | st[p] = Math.min(st[l], st[r]); 30 | } 31 | } 32 | /* 33 | void propagate(int p, int L, int R, int val) { 34 | if (val == neutro) return; 35 | st[p] = val; 36 | lazy[p] = neutro; 37 | if (L != R) { 38 | lazy[left(p)] = val; 39 | lazy[right(p)] = val; 40 | } 41 | } 42 | */ 43 | int query(int p, int L, int R, int i, int j) { 44 | // propagate(p, L, R, lazy[p]); 45 | if (i > R || j < L) return neutro; 46 | if (i <= L && j >= R) return st[p]; 47 | int m = (L+R)/2, l = left(p), r = right(p); 48 | l = query(l, L, m, i, j); 49 | r = query(r, m + 1, R, i, j); 50 | return Math.min(l, r); 51 | } 52 | 53 | void update(int p, int L, int R, int i, int j, int val) { 54 | // propagate(p, L, R, lazy[p]); 55 | if (i > R || j < L) return; 56 | if (i <= L && j >= R) st[p] = val; // propagate(p, L, R, val); 57 | else { 58 | int m = (L+R)/2, l = left(p), r = right(p); 59 | update(l, L, m, i, j, val); 60 | update(r, m + 1, R, i, j, val); 61 | st[p] = Math.min(st[l], st[r]); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /java [outdated]/Data Structures/Sparse Table.java: -------------------------------------------------------------------------------- 1 | Estructura de datos que permite procesar consultas por rangos. 2 | 3 | static int MAX_N = 1000; 4 | static int K = (int)(Math.log(MAX_N)/Math.log(2))+1; 5 | static int st[][] = new int[MAX_N][K]; 6 | static int _log2[] = new int[MAX_N+1]; 7 | static int A[] = new int[MAX_N]; 8 | int n; 9 | 10 | void calc_log2() { 11 | _log2[1] = 0; 12 | for (int i = 2; i <= MAX_N; i++) _log2[i] = _log2[i/2] + 1; 13 | } 14 | 15 | void build() { 16 | for (int i = 0; i < n; i++) st[i][0] = A[i]; 17 | for (int j = 1; j <= K; j++) 18 | for (int i = 0; i + (1 << j) <= n; i++) 19 | st[i][j] = Math.min(st[i][j-1], st[i + (1 << (j - 1))][j - 1]); 20 | } 21 | 22 | int rmq(int i, int j) { 23 | int k = _log2[j-i+1]; 24 | return Math.min(st[i][k], st[j - (1 << k) + 1][k]); 25 | } 26 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Coin change.java: -------------------------------------------------------------------------------- 1 | Problemas clásicos de moneda con DP 2 | 3 | static final int MAX_COINS = 1005; 4 | static final int MAX_VALUE = 1005; 5 | static final int INF = (int) (2e9); 6 | static int coins[] = new int[MAX_COINS]; 7 | static int dp[] = new int[MAX_VALUE]; 8 | static ArrayList rb = new ArrayList<>(); 9 | 10 | // Calcula el número de formas para valores entre 1 y value. SIN CONTAR PERMUTACIONES 11 | static void ways(int value) { 12 | dp = new int[MAX_VALUE]; 13 | dp[0] = 1; 14 | for (int c: coins) { 15 | for (int i = 1; i <= value; i++) { 16 | if (i - c >= 0) dp[i] += dp[i - c]; 17 | } 18 | } 19 | } 20 | 21 | // Calcula el número de formas para valores entre 1 y value. CONTANDO PERMUTACIONES 22 | static void ways_perm(int value) { 23 | dp = new int[MAX_VALUE]; 24 | dp[0] = 1; 25 | for (int i = 1; i <= value; i++) { 26 | for (int c: coins) { 27 | if (i - c >= 0) dp[i] += dp[i - c]; 28 | } 29 | } 30 | } 31 | 32 | // Calcula el minimo numero de monedas necesarias para los valores entre 1 y value. 33 | static void min_coin(int value) { 34 | dp = new int[MAX_VALUE]; 35 | for (int i = 1; i <= value; i++) { 36 | dp[i] = INF; 37 | for (int c: coins) { 38 | if (i - c >= 0) dp[i] = Math.min(dp[i], dp[i - c] + 1); 39 | } 40 | } 41 | } 42 | 43 | // Guarda en el vector rb las monedas usadas en min_coin. 44 | static void build_ways(int value) { 45 | rb.clear(); 46 | for (int c = MAX_COINS - 1; c >= 0; c--) { 47 | if (value == 0) return; 48 | while (value - coins[c]>= 0 && dp[value] == dp[value - coins[c]] + 1) { 49 | rb.add(coins[c]); 50 | value -= coins[c]; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Knapsack.java: -------------------------------------------------------------------------------- 1 | Dados N articulos, cada uno con su propio valor y peso y un tamaño maximo de una mochila, se debe calcular el valor maximo de los elementos que es posible llevar. 2 | Debe seleccionarse un subconjunto de objetos, de tal manera que quepan en la mochila y representen el mayor valor posible. 3 | 4 | static int MAX_WEIGHT = 40; // Peso maximo de la mochila 5 | static int MAX_N = 1000; // Numero maximo de objetos 6 | static int N; // Numero de objetos 7 | static int prices[] = new int[MAX_N]; // precios de cada producto 8 | static int weights[] = new int[MAX_N]; // pesos de cada producto 9 | static int memo[][]= new int[MAX_N][MAX_WEIGHT]; // tabla dp 10 | 11 | // El metodo debe llamarse con 0 en el id, y la capacidad de la mochila en w 12 | static int knapsack(int id, int w) { 13 | if (id == N || w == 0) return 0; 14 | if (memo[id][w] != -1) return memo[id][w]; 15 | if (weights[id] > w) memo[id][w] = knapsack(id + 1, w); 16 | else memo[id][w] = Math.max(knapsack(id + 1, w), prices[id] + knapsack(id + 1, w - weights[id])); 17 | return memo[id][w]; 18 | } 19 | // Antes de llamar al metodo, todos los campos de la tabla memo deben iniciarse a -1 20 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Longest Common Subsequence.java: -------------------------------------------------------------------------------- 1 | Dados dos Strings, encuentra el largo de la subsecuencia en común mas larga entre ellas. 2 | 3 | static int M_MAX = 20; // Máximo size del String 1 4 | static int N_MAX = 20; // Máximo size del String 2 5 | static int m, n; // Size de Strings 1 y 2 6 | static char X[]; // toCharArray del String 1 7 | static char Y[]; // toCharArray del String 2 8 | static int memo[][] = new int[M_MAX + 1][N_MAX + 1]; 9 | 10 | static int lcs(int m, int n) { 11 | for (int i = 0; i <= m; i++) { 12 | for (int j = 0; j <= n; j++) { 13 | if (i == 0 || j == 0) memo[i][j] = 0; 14 | else if (X[i - 1] == Y[j - 1]) memo[i][j] = memo[i - 1][j - 1] + 1; 15 | else memo[i][j] = Math.max(memo[i - 1][j], memo[i][j - 1]); 16 | } 17 | } 18 | return memo[m][n]; 19 | } 20 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Longest increasing subsequence.java: -------------------------------------------------------------------------------- 1 | Halla la longitud de la subsecuencia creciente mas larga. MAX debe definirse en el tamaño limite del array, n es el tamaño del array. Si debe admitir valores repetidos, cambiar el < de I[mid] < values[i] por <= 2 | 3 | static int inf = 2000000000; 4 | static int MAX = 100000; 5 | static int n; 6 | static int values[] = new int[MAX + 5]; 7 | static int L[] = new int[MAX + 5]; 8 | static int I[] = new int[MAX + 5]; 9 | 10 | static int lis() { 11 | int i, low, high, mid; 12 | I[0] = -inf; 13 | for (i = 1; i <= n; i++) I[i] = inf; 14 | int ans = 0; 15 | for (i = 0; i < n; i++) { 16 | low = mid = 0; 17 | high = ans; 18 | while (low <= high) { 19 | mid = (low + high) / 2; 20 | if (I[mid] < values[i]) low = mid + 1; 21 | else high = mid - 1; 22 | } 23 | I[low] = values[i]; 24 | if (ans < low) ans = low; 25 | } 26 | return ans; 27 | } 28 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Max Range 2D.java: -------------------------------------------------------------------------------- 1 | // Cambiar infinito por el mínimo valor posible 2 | static int INF = -100000007; 3 | static int n, m; // filas y columnas 4 | static final int MAX_N = 105, MAX_M = 105; 5 | static int values[][] = new int[MAX_N][MAX_M]; 6 | 7 | static int max_range_sum2D() { 8 | for (int i=0; i0) values[i][j] += values[i-1][j]; 11 | if (j>0) values[i][j] += values[i][j-1]; 12 | if (i>0 && j>0) values[i][j] -= values[i-1][j-1]; 13 | } 14 | } 15 | int max_mat = INF; 16 | for (int i=0; i0) sub_mat -= values[i-1][k]; 22 | if (j>0) sub_mat -= values[h][j-1]; 23 | if (i>0 && j>0) sub_mat += values[i-1][j-1]; 24 | max_mat = Math.max(sub_mat, max_mat); 25 | } 26 | } 27 | } 28 | } 29 | return max_mat; 30 | } 31 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Max Range 3D.java: -------------------------------------------------------------------------------- 1 | // Cambiar valores a, b, c por límites correspondientes 2 | static int a=20, b=20, c=20; 3 | static long acum[][][] = new long [a][b][c]; 4 | static long INF = -10000000000007L; 5 | 6 | static long max_range_3D() { 7 | for (int x=0; x0) acum[x][y][z] += acum[x-1][y][z]; 11 | if (y>0) acum[x][y][z] += acum[x][y-1][z]; 12 | if (z>0) acum[x][y][z] += acum[x][y][z-1]; 13 | if (x>0 && y>0) acum[x][y][z] -= acum[x-1][y-1][z]; 14 | if (x>0 && z>0) acum[x][y][z] -= acum[x-1][y][z-1]; 15 | if (y>0 && z>0) acum[x][y][z] -= acum[x][y-1][z-1]; 16 | if (x>0 && y>0 && z>0) acum[x][y][z] += acum[x-1][y-1][z-1]; 17 | } 18 | } 19 | } 20 | long max_value = INF; 21 | for (int x=0; x0) aux -= acum[x-1][k][l]; 29 | if (y>0) aux -= acum[h][y-1][l]; 30 | if (z>0) aux -= acum[x][k][z-1]; 31 | if (x>0 && y>0) aux += acum[x-1][y-1][l]; 32 | if (x>0 && z>0) aux += acum[x-1][k][z-1]; 33 | if (z>0 && y>0) aux += acum[h][y-1][z-1]; 34 | if (x>0 && y>0 && z>0) aux -= acum[x-1][y-1][z-1]; 35 | max_value = Math.max(max_value, aux); 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | return max_value; 43 | } 44 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Max Range Sum.java: -------------------------------------------------------------------------------- 1 | Dado un arreglo de enteros, retorna la máxima suma de un rango de la lista. 2 | 3 | static int maxRangeSum(int[] a) { 4 | int sum = 0, ans = 0; 5 | for (int i = 0; i < a.length; i++) { 6 | if (sum + a[i] >= 0) { 7 | sum += a[i]; 8 | ans = Math.max(ans, sum); 9 | } else sum = 0; 10 | } 11 | return ans; 12 | } 13 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Min Max Range.java: -------------------------------------------------------------------------------- 1 | // Devuelve el el minimo de los maximos entre pares de rangos consecutivos haciendo cortes en el Array. 2 | 3 | static final int MAX = 1005; 4 | static long dp[][] = new long[MAX][MAX]; 5 | static long sum_ran[][] = new long [MAX][MAX]; 6 | static int N; 7 | 8 | static long f(int i, int cuts) { 9 | if (cuts == 0) return sum_ran[i][N-1]; 10 | if (i == N) return 0; 11 | long ans = dp[i][cuts]; 12 | if (ans != - 1) return ans; 13 | for (int j = i; j < N; j++) { 14 | ans = Math.min(ans, Math.max(sum_ran[i][j], f(i + 1, cuts - 1))); 15 | } 16 | return ans; 17 | } 18 | -------------------------------------------------------------------------------- /java [outdated]/Dynamic Programming/Traveling Salesman Problem.java: -------------------------------------------------------------------------------- 1 | // Problema del viajero. Devuelve la ruta minima haciendo un tour visitando todas los nodos (ciudades) una unica vez. 2 | 3 | static final int MAX = 18; 4 | static int target; // Inicializarlo para (1< rb = new ArrayList<>(); 9 | static final int INF = (int) (2e9); 10 | 11 | // Llamar para TSP(0, -1) Si no empieza de ninguna ciudad especificia 12 | // De lo contrario llamar TSP(0, 0) 13 | static int TSP(int mask, int u) { 14 | if (mask == target) { 15 | return 0; 16 | // O en su defecto el costo extra tras haber visitado todas las ciudades. EJ: Volver a la ciudad principal 17 | } 18 | if (u == -1) { 19 | int ans = INF; 20 | for (int i = 0; i < N; i++) { 21 | ans = Math.min(ans, TSP(mask | (1< P) { 4 | double result = 0.0; 5 | for (int i = 0; i < P.size()-1; i++) { 6 | result += ((P.get(i).x * P.get(i + 1).y) - (P.get(i + 1).x * P.get(i).y)); 7 | } 8 | return Math.abs(result) / 2.0; 9 | } 10 | -------------------------------------------------------------------------------- /java [outdated]/Geometry/Collinear Points.java: -------------------------------------------------------------------------------- 1 | Determina si el punto r está en la misma linea que los puntos p y q. IMPORTANTE: Deben incluirse las estructuras point y vec. 2 | 3 | static double cross(Vec a, Vec b) { 4 | return a.x * b.y - a.y * b.x; 5 | } 6 | 7 | static boolean collinear(Point p, Point q, Point r) { 8 | return Math.abs(cross(toVector(p, q), toVector(p, r))) < 1e-9; 9 | } 10 | -------------------------------------------------------------------------------- /java [outdated]/Geometry/Convex Hull.java: -------------------------------------------------------------------------------- 1 | Retorna el polígono convexo mas pequeño que cubre (ya sea en el borde o en el interior) un set de puntos. Recibe un vector de puntos, y retorna un vector de puntos indicando el polígono resultante. Es necesario que esten definidos previamente: 2 | 3 | Estructuras: point y vec 4 | Métodos: collinear, euclideanDistance, ccw (de inPolygon) y angle. 5 | 6 | import java.util.ArrayList; 7 | import java.util.Comparator; 8 | import java.util.Collections; 9 | 10 | static ArrayList ConvexHull (ArrayList P) { 11 | int i, j, n = (int)P.size(); 12 | if (n <= 3) { 13 | if (P.get(0).x != P.get(n-1).x || P.get(0).y != P.get(n-1).y) P.add(P.get(0)); 14 | return P; 15 | } 16 | int P0 = 0; 17 | for (i = 1; i < n; i++) 18 | if (P.get(i).y < P.get(P0).y || (P.get(i).y == P.get(P0).y && P.get(i).x > P.get(P0).x)) P0 = i; 19 | Point temp = P.get(0); P.set(0, P.get(P0)); P.set(P0, temp); 20 | Point pivot = P.get(0); 21 | Collections.sort(P, new Comparator() { 22 | public int compare(Point a, Point b) { 23 | if (collinear(pivot, a, b)) return euclideanDistance(pivot, a) < euclideanDistance(pivot, b) ? -1 : 1; 24 | double d1x = a.x - pivot.x, d1y = a.y - pivot.y; 25 | double d2x = b.x - pivot.x, d2y = b.y - pivot.y; 26 | return (Math.atan2(d1y, d1x) - Math.atan2(d2y, d2x)) < 0 ? -1 : 1; 27 | } 28 | }); 29 | ArrayList S = new ArrayList(); 30 | S.add(P.get(n-1)); S.add(P.get(0)); S.add(P.get(1)); 31 | i = 2; 32 | while (i < n) { 33 | j = S.size() - 1; 34 | if (ccw(S.get(j-1), S.get(j), P.get(i))) S.add(P.get(i++)); 35 | else S.remove(S.size() - 1); 36 | } 37 | return S; 38 | } 39 | -------------------------------------------------------------------------------- /java [outdated]/Geometry/Euclidean Distance.java: -------------------------------------------------------------------------------- 1 | Halla la distancia euclideana de 2 puntos en dos dimensiones (x, y). Para usar el primer método, debe definirse previamente la clase Point 2 | 3 | /*Trabajando con la clase Point*/ 4 | static double euclideanDistance(Point p1, Point p2) { 5 | return Math.hypot(p1.x - p2.x, p1.y - p2.y); 6 | } 7 | /*Trabajando con los valores x y y de cada punto*/ 8 | static double euclideanDistance(double x1, double y1, double x2, double y2) { 9 | return Math.hypot(x2 - x1, y2 - y1); 10 | } 11 | -------------------------------------------------------------------------------- /java [outdated]/Geometry/Gometric Vector.java: -------------------------------------------------------------------------------- 1 | Dados dos puntos A y B, crea el vector A->B. IMPORTANTE: Debe definirse la clase Point. Es llamado Vec para no confundirlo con vector como colección de elementos. 2 | 3 | static class Vec { 4 | public double x, y; 5 | public Vec(double _x, double _y) { 6 | this.x = _x; 7 | this.y = _y; 8 | } 9 | } 10 | 11 | static Vec toVector(Point a, Point b) { 12 | return new Vec(b.x - a.x, b.y - a.y); 13 | } 14 | -------------------------------------------------------------------------------- /java [outdated]/Geometry/Perimeter.java: -------------------------------------------------------------------------------- 1 | Calcula el perímetro de un polígono representado como un vector de puntos. IMPORTANTE: Definir P[0] = P[n-1] para cerrar el polígono. La estructura point debe estar definida, al igual que el método euclideanDistance. 2 | 3 | public static double perimeter(ArrayList P) { 4 | double result = 0.0; 5 | for (int i = 0; i < P.size()-1; i++) { 6 | result += euclideanDistance(P.get(i), P.get(i+1)); 7 | } 8 | return result; 9 | } 10 | -------------------------------------------------------------------------------- /java [outdated]/Geometry/Point in Polygon.java: -------------------------------------------------------------------------------- 1 | Determina si un punto pt se encuentra en el polígono P. Este polígono se define como un vector de puntos, donde el punto 0 y n-1 son el mismo. IMPORTANTE: Deben incluirse las estructuras point y vec, ademas del método angle y el método cross que se encuentra en Collinear Points. 2 | 3 | static boolean ccw(Point p, Point q, Point r) { 4 | return cross(toVector(p, q), toVector(p, r)) > 0; 5 | } 6 | 7 | static boolean inPolygon(Point pt, ArrayList P) { 8 | if (P.size() == 0) return false; 9 | double sum = 0; 10 | for (int i = 0; i < P.size()-1; i++) { 11 | if (ccw(pt, P.get(i), P.get(i+1))) sum += angle(P.get(i), pt, P.get(i+1)); 12 | else sum -= angle(P.get(i), pt, P.get(i+1)); 13 | } 14 | if (Math.abs(Math.abs(sum) - 2*Math.acos(-1.0)) < 1e-9) return true; 15 | return false; 16 | } 17 | -------------------------------------------------------------------------------- /java [outdated]/Geometry/Point.java: -------------------------------------------------------------------------------- 1 | La clase punto será la base sobre la cual se ejecuten otros algoritmos. 2 | 3 | static class Point { 4 | public double x, y; 5 | public Point() { this.x = this.y = 0.0; } 6 | public Point(double _x, double _y) { 7 | this.x = _x; 8 | this.y = _y; 9 | } 10 | public boolean equals(Point other) { 11 | if (Math.abs(this.x - other.x) < 1e-9 && (Math.abs(this.y - other.y) < 1e-9)) return true; 12 | return false; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /java [outdated]/Geometry/Sexagesimal degrees and radians.java: -------------------------------------------------------------------------------- 1 | Conversiones de grados sexagesimales a radianes y viceversa. 2 | 3 | static double DegToRad(double d) { 4 | return d * Math.PI / 180.0; 5 | } 6 | 7 | static double RadToDeg(double r) { 8 | return r * 180.0 / Math.PI; 9 | } 10 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/BFS.java: -------------------------------------------------------------------------------- 1 | Búsqueda en anchura sobre grafos. Recibe un nodo inicial u y visita todos los nodos alcanzables desde u. 2 | BFS tambien halla la distancia mas corta entre el nodo inicial u y los demas nodos si todas las aristas tienen peso 1. 3 | 4 | static final int MAX = 100005; // Cantidad maxima de nodos 5 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 6 | static long dist[] = new long[MAX]; // Almacena la distancia a cada nodo 7 | static int N, M; // Cantidad de nodos y aristas 8 | 9 | void bfs(int u) { 10 | Queue q = new LinkedList<>(); 11 | q.add(u); 12 | dist[u] = 0; 13 | while (!q.isEmpty()) { 14 | u = q.poll(); 15 | for (int v : g[u]) { 16 | if (dist[v] == -1) { 17 | dist[v] = dist[u] + 1; 18 | q.add(v); 19 | } 20 | } 21 | } 22 | } 23 | 24 | static void init() { 25 | for (int i = 0; i <= N; i++) { 26 | g[i] = new ArrayList<>(); 27 | dist[i] = -1; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Bipartite Check.java: -------------------------------------------------------------------------------- 1 | Modificación del BFS para detectar si un grafo es bipartito. 2 | 3 | static final int MAX = 100005; // Cantidad maxima de nodos 4 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 5 | static int color[] = new int[MAX]; // Almacena el color de cada nodo 6 | static boolean bipartite; // true si el grafo es bipartito 7 | static int N, M; // Cantidad de nodos y aristas 8 | 9 | void bfs(int u) { 10 | Queue q = new LinkedList<>(); 11 | q.add(u); 12 | color[u] = 0; 13 | while (!q.isEmpty()) { 14 | u = q.poll(); 15 | for (int v : g[u]) { 16 | if (color[v] == -1) { 17 | color[v] = color[u]^1; 18 | q.add(v); 19 | } else if (color[v] == color[u]) { 20 | bipartite = false; 21 | return; 22 | } 23 | } 24 | } 25 | } 26 | 27 | static void init() { 28 | bipartite = true; 29 | for (int i = 0; i <= N; i++) { 30 | g[i] = new ArrayList<>(); 31 | color[i] = -1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/DFS.java: -------------------------------------------------------------------------------- 1 | Búsqueda en profundidad sobre grafos. Recibe un nodo inicial u y visita todos los nodos alcanzables desde u. 2 | DFS puede ser usado para contar la cantidad de componentes conexas en un grafo y puede ser modificado para que retorne información de los nodos dependiendo del problema. 3 | 4 | static final int MAX = 100005; // Cantidad maxima de nodos 5 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 6 | static boolean[] vis = new boolean[MAX]; // Marca los nodos ya visitados 7 | static int N, M; // Cantidad de nodos y aristas 8 | 9 | static void dfs(int u) { 10 | vis[u] = true; 11 | for (int v : g[u]) { 12 | if (!vis[v]) dfs(v); 13 | } 14 | } 15 | 16 | static void init() { 17 | for (int i = 0; i <= N; i++) { 18 | g[i] = new ArrayList<>(); 19 | vis[i] = false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Dijkstra.java: -------------------------------------------------------------------------------- 1 | Dado un grafo con pesos no negativos halla la ruta de costo mínimo entre un nodo inicial u y todos los demás nodos. 2 | 3 | static long INF = (1l<<62); 4 | static final int MAX = 100005; // Cantidad maxima de nodos 5 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 6 | static boolean[] vis = new boolean[MAX]; // Marca los nodos ya visitados 7 | static int pre[] = new int[MAX]; // Almacena el nodo anterior para construir las rutas 8 | static long dist[] = new long[MAX]; // Almacena la distancia a cada nodo 9 | static int N, M; // Cantidad de nodos y aristas 10 | 11 | static class edge implements Comparable { 12 | int v; 13 | long w; 14 | 15 | edge(int _v, long _w) { 16 | v = _v; 17 | w = _w; 18 | } 19 | 20 | @Override 21 | public int compareTo(edge o) { 22 | if (w > o.w) return 1; 23 | else return -1; 24 | } 25 | } 26 | 27 | static void dijkstra(int u) { 28 | PriorityQueue pq = new PriorityQueue<>(); 29 | pq.add(new edge(u, 0)); 30 | dist[u] = 0; 31 | while (!pq.isEmpty()) { 32 | u = pq.poll().v; 33 | if (!vis[u]) { 34 | vis[u] = true; 35 | for (edge nx : g[u]) { 36 | int v = nx.v; 37 | if (!vis[v] && dist[v] > dist[u] + nx.w) { 38 | dist[v] = dist[u] + nx.w; 39 | pre[v] = u; 40 | pq.add(new edge(v, dist[v])); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | 47 | static void init() { 48 | for (int i = 0; i <= N; i++) { 49 | g[i] = new ArrayList<>(); 50 | dist[i] = INF; 51 | vis[i] = false; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/FloodFill.java: -------------------------------------------------------------------------------- 1 | Dado un grafo implicito como matriz, "colorea" y cuenta el tamaño de las componentes conexas. 2 | Este método debe ser llamado con las coordenadas (i, j) donde se inicia el recorrido, busca cada caracter c1 de la componente, los remplaza por el caracter c2 y retorna el tamaño. 3 | 4 | static final int tam = 1000; // Tamanio maximo de la matriz 5 | static int dy[] = {1, 1, 0,-1,-1,-1, 0, 1}; // Posibles movimientos: 6 | static int dx[] = {0, 1, 1, 1, 0,-1,-1,-1}; // (8 direcciones) 7 | static char grid[][] = new char[tam][tam]; // Matriz de caracteres 8 | static int Y, X; // Tamanio de la matriz 9 | 10 | static int floodfill(int y, int x, char c1, char c2) { 11 | if (y < 0 || y >= Y || x < 0 || x >= X) return 0; 12 | if (grid[y][x] != c1) return 0; 13 | grid[y][x] = c2; 14 | int ans = 1; 15 | for (int i = 0; i < 8; i++) { 16 | ans += floodfill(y + dy[i], x + dx[i], c1, c2); 17 | } 18 | return ans; 19 | } 20 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Floyd Warshall.java: -------------------------------------------------------------------------------- 1 | Dado un grafo halla la distancia mínima entre cualquier par de nodos. g[i][j] guardará la distancia mínima entre el nodo i y el j. 2 | 3 | static final int INF = (1<<30); 4 | static final int MAX = 505; // Cantidad maxima de nodos 5 | static int g[][]= new int[MAX][MAX]; // Matriz de adyacencia 6 | static int N, M; // Cantidad de nodos y aristas 7 | 8 | static void floydWarshall() { 9 | for (int k = 0; k < N; k++) 10 | for (int i = 0; i < N; i++) 11 | for (int j = 0; j < N; j++) 12 | g[i][j] = Math.min(g[i][j], g[i][k] + g[k][j]); 13 | } 14 | 15 | static void init() { 16 | for (int i = 0; i <= N; i++) { 17 | for (int j = 0; j <= N; j++) { 18 | g[i][j] = INF; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Kruskal.java: -------------------------------------------------------------------------------- 1 | Dado un grafo con pesos halla su árbol cobertor mínimo. 2 | IMPORTANTE: Debe agregarse Disjoint Set. 3 | 4 | static class edge implements Comparable { 5 | int u, v, w; 6 | edge(int _u, int _v, int _w) { 7 | u = _u; 8 | v = _v; 9 | w = _w; 10 | } 11 | 12 | @Override 13 | public int compareTo(edge o) { 14 | if (w > o.w) return 1; 15 | else return -1; 16 | } 17 | } 18 | 19 | static class par { 20 | int F, S; 21 | 22 | par(int f, int s) { 23 | F = f; 24 | S = s; 25 | } 26 | } 27 | 28 | static final int MAX = 100005; // Cantidad maxima de nodos 29 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 30 | static ArrayList e = new ArrayList<>(); // Lista de aristas 31 | static int N, M; // Cantidad de nodos y aristas 32 | 33 | static void kruskall() { 34 | Collections.sort(e); 35 | dsu ds = new dsu(N); 36 | int sz = 0; 37 | for (edge ed: e) { 38 | if (ds.find(ed.u) != ds.find(ed.v)) { 39 | ds.unite(ed.u, ed.v); 40 | g[ed.u].add(new par(ed.v, ed.w)); 41 | g[ed.v].add(new par(ed.u, ed.w)); 42 | if (++sz == N - 1) { 43 | break; 44 | } 45 | } 46 | } 47 | } 48 | 49 | static void init() { 50 | e.clear(); 51 | for (int i = 0; i <= N; i++) { 52 | g[i] = new ArrayList<>(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/LoopCheck.java: -------------------------------------------------------------------------------- 1 | Determina si un Grafo DIRIGIDO tiene o no ciclos. 2 | SE DEBEN LIMPIAR LAS ESTRUCTURAS DE DATOS ANTES DE UTILIZARSE 3 | 4 | static final int MAX = 10010; // Cantidad maxima de nodos 5 | static int v; // Cantidad de Nodos del grafo 6 | static ArrayList ady[] = new ArrayList[MAX]; // Estructura para almacenar el grafo 7 | static int dfs_num[] = new int[MAX]; 8 | static boolean loops; // Bandera de ciclos en el grafo 9 | 10 | /* DFS_NUM STATES 11 | 2 - Explored 12 | 3 - Visited 13 | -1 - Unvisited 14 | 15 | Este metodo debe ser llamado desde un nodo inicial u. 16 | Cortara su ejecucion en el momento que encuentre algun ciclo en el grafo. 17 | */ 18 | static void graphCheck(int u) { 19 | int j, next; 20 | if (loops) return; 21 | dfs_num[u] = 2; 22 | for (j = 0; j < ady[u].size(); j++) { 23 | next = ady[u].get(j); 24 | if (dfs_num[next] == -1) graphCheck(next); 25 | else if (dfs_num[next] == 2) { 26 | loops = true; 27 | break; 28 | } 29 | } 30 | dfs_num[u] = 3; 31 | } 32 | 33 | public static void main(String args[]) { 34 | for (int s = 1; s <= v && !loops; s++) { // Por si el grafo es NO conexo 35 | if (dfs_num[s] == -1) graphCheck(s); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Lowest Common Ancestor.java: -------------------------------------------------------------------------------- 1 | Dados los nodos u y v de un arbol determina cual es el ancestro comun mas bajo entre u y v. 2 | *Tambien puede determinar la arista de peso maximo entre los nodos u y v (Para esto quitar los "// ") 3 | SE DEBE EJECUTAR EL METODO build() ANTES DE UTILIZARSE 4 | 5 | static final int MAX = 100005; // Cantidad maxima de nodos 6 | static final int LOG2 = 17; // log2(MAX)+1 7 | // ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 8 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 9 | static int dep[] = new int[MAX]; // Almacena la profundidad de cada nodo 10 | static int par[][] = new int[MAX][LOG2]; // Almacena los padres para responder las consultas 11 | // int rmq[][] = new int[MAX][LOG2]; // Almacena los pesos para responder las consultas 12 | static int N, M; // Cantidad de nodos y aristas 13 | 14 | /*static class edge { 15 | int v, w; 16 | 17 | edge(int _v, int _w) { 18 | v = _v; 19 | w = _w; 20 | } 21 | };*/ 22 | 23 | static int lca(int u, int v) { 24 | // int ans = -1; 25 | if (dep[u] < dep[v]) { 26 | int aux = u; 27 | u = v; 28 | v = aux; 29 | } 30 | int diff = dep[u] - dep[v]; 31 | for (int i = LOG2-1; i >= 0; i--) { 32 | if ((diff & (1 << i))> 0) { 33 | // ans = Math.max(ans, rmq[u][i]); 34 | u = par[u][i]; 35 | } 36 | } 37 | // if (u == v) return ans; 38 | if (u == v) return u; 39 | for (int i = LOG2-1; i >= 0; i--) { 40 | if (par[u][i] != par[v][i]) { 41 | // ans = Math.max(ans, Math.max(rmq[u][i], rmq[v][i])); 42 | u = par[u][i]; 43 | v = par[v][i]; 44 | } 45 | } 46 | // return Math.max(ans, Math.max(rmq[u][0], rmq[v][0])); 47 | return par[u][0]; 48 | } 49 | 50 | static void dfs(int u, int p, int d) { 51 | dep[u] = d; 52 | par[u][0] = p; 53 | for (int v /* edge ed*/ : g[u]) { 54 | // int v = ed.v; 55 | if (v != p) { 56 | // rmq[v][0] = ed.w; 57 | dfs(v, u, d + 1); 58 | } 59 | } 60 | } 61 | 62 | static void build() { 63 | for (int i = 0; i < N; i++) dep[i] = -1; 64 | for (int i = 0; i < N; i++) { 65 | if (dep[i] == -1) { 66 | // rmq[i][0] = -1; 67 | dfs(i, i, 0); 68 | } 69 | } 70 | for (int j = 0; j < LOG2-1; j++) { 71 | for (int i = 0; i < N; i++) { 72 | par[i][j+1] = par[par[i][j]][j]; 73 | // rmq[i][j+1] = Math.max(rmq[par[i][j]][j], rmq[i][j]); 74 | } 75 | } 76 | } 77 | 78 | static void init() { 79 | for (int i = 0; i <= N; i++) { 80 | g[i] = new ArrayList<>(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Maxflow.java: -------------------------------------------------------------------------------- 1 | Dado un grafo, halla el máximo flujo entre una fuente s y un sumidero t. 2 | SE DEBEN LIMPIAR LAS ESTRUCTURAS DE DATOS ANTES DE UTILIZARSE 3 | 4 | static int n; // Cantidad de nodos del grafo 5 | static ArrayList ady[] = new ArrayList[105]; // lista de Adyacencia 6 | static int capacity[][] = new int[105][105]; // Capacidad de aristas de la red 7 | static int flow[][] = new int[105][105]; // Flujo de cada arista 8 | static int prev[] = new int[105]; 9 | 10 | static void connect(int i, int j, int cap) { 11 | ady[i].add(j); 12 | ady[j].add(i); 13 | capacity[i][j] += cap; 14 | // Si el grafo es dirigido no hacer esta linea 15 | // capacity[j][i] += cap; 16 | } 17 | 18 | static int maxflow(int s, int t, int n) { // s=fuente, t=sumidero, n=numero de nodos 19 | int i, j, maxFlow, u, v, extra, start, end; 20 | for (i = 0; i <= n; i++) { 21 | for (j = 0; j <= n; j++) { 22 | flow[i][j] = 0; 23 | } 24 | } 25 | maxFlow = 0; 26 | while (true) { 27 | for (i = 0; i <= n; i++) prev[i] = -1; 28 | Queue q = new LinkedList(); 29 | q.add(s); 30 | prev[s] = -2; 31 | while (!q.isEmpty()) { 32 | u = q.poll(); 33 | if (u == t) break; 34 | for (j = 0; j < ady[u].size(); j++) { 35 | v = ady[u].get(j); 36 | if (prev[v] == -1 && capacity[u][v] - flow[u][v] > 0) { 37 | q.add(v); 38 | prev[v] = u; 39 | } 40 | } 41 | } 42 | if (prev[t] == -1) break; 43 | extra = Integer.MAX_VALUE; 44 | end = t; 45 | while (end != s) { 46 | start = prev[end]; 47 | extra = Math.min(extra, capacity[start][end]-flow[start][end]); 48 | end = start; 49 | } 50 | end = t; 51 | while (end != s) { 52 | start = prev[end]; 53 | flow[start][end] += extra; 54 | flow[end][start] = -flow[start][end]; 55 | end = start; 56 | } 57 | maxFlow += extra; 58 | } 59 | return maxFlow; 60 | } 61 | 62 | public static void main(String args[]) { 63 | // Para cada arista 64 | connect(s, d, f); // origen, destino, flujo 65 | } 66 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Prim.java: -------------------------------------------------------------------------------- 1 | Dado un grafo halla el costo total de su arbol cobertor mínimo. 2 | 3 | static final int MAX = 100005; // Cantidad maxima de nodos 4 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 5 | static boolean[] vis = new boolean[MAX]; // Marca los nodos ya visitados 6 | static long ans; // Costo total del arbol cobertor minimo 7 | static int N, M; // Cantidad de nodos y aristas 8 | 9 | static class edge implements Comparable { 10 | int v; 11 | long w; 12 | 13 | edge(int _v, long _w) { 14 | v = _v; 15 | w = _w; 16 | } 17 | 18 | @Override 19 | public int compareTo(edge o) { 20 | if (w > o.w) return 1; 21 | return -1; 22 | } 23 | } 24 | 25 | static void prim() { 26 | PriorityQueue pq = new PriorityQueue<>(); 27 | vis[0] = true; 28 | for (edge ed : g[0]) { 29 | int v = ed.v; 30 | if (!vis[v]) pq.add(new edge(v, ed.w)); 31 | } 32 | while (!pq.isEmpty()) { 33 | edge ed = pq.poll(); 34 | int u = ed.v; 35 | if (!vis[u]) { 36 | ans += ed.w; 37 | vis[u] = true; 38 | for (edge e : g[u]) { 39 | int v = e.v; 40 | if (!vis[v]) pq.add(new edge(v, e.w)); 41 | } 42 | } 43 | } 44 | } 45 | 46 | static void init() { 47 | ans = 0; 48 | for (int i = 0; i <= N; i++) { 49 | g[i] = new ArrayList(); 50 | vis[i] = false; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Puentes itmos.java: -------------------------------------------------------------------------------- 1 | Algoritmo para hallar los puentes e itsmos en un grafo no dirigido. Requiere de la clase Edge. 2 | SE DEBEN LIMPIAR LAS ESTRUCTURAS DE DATOS ANTES DE UTILIZARSE 3 | 4 | static int n, e; // vertices, arcos 5 | static int MAX=1010; 6 | static ArrayList ady[]=new ArrayList [MAX]; 7 | static boolean marked[]=new boolean [MAX]; 8 | static int prev[]=new int [MAX]; 9 | static int dfs_low[]=new int [MAX]; 10 | static int dfs_num[]=new int [MAX]; 11 | static boolean itsmos[]=new int [MAX]; 12 | static ArrayList bridges; 13 | static int dfsRoot, rootChildren, cont; 14 | 15 | /* Recibe el nodo inicial */ 16 | static void dfs(int u) { 17 | dfs_low[u] = dfs_num[u] = cont; 18 | cont++; 19 | marked[u] = true; 20 | int j, v; 21 | 22 | for (j = 0; j < ady[u].size(); j++) { 23 | v = ady[u].get(j); 24 | if (!marked[v]) { 25 | prev[v] = u; 26 | // Caso especial 27 | if (u == dfsRoot) rootChildren++; 28 | dfs(v); 29 | 30 | // Itmos 31 | if (dfs_low[v] >= dfs_num[u]) itsmos[u] = true; 32 | 33 | // Puentes 34 | if (dfs_low[v] > dfs_num[u]) bridges.add(new Edge(Math.min(u, v), Math.max(u, v))); 35 | 36 | dfs_low[u] = Math.min(dfs_low[u], dfs_low[v]); 37 | } else if (v != prev[u]) dfs_low[u] = Math.min(dfs_low[u], dfs_num[v]); 38 | } 39 | } 40 | 41 | public static void main(String args[]) { 42 | dfs(dfsRoot); 43 | /* Caso especial */ 44 | itmos[dfsRoot] = (itmos[dfsRoot] && rootChildren > 1) ? true : false; 45 | } 46 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Tarjan.java: -------------------------------------------------------------------------------- 1 | Dado un grafo dirigido halla las componentes fuertemente conexas (SCC). 2 | 3 | static final int MAX = 100005; // Cantidad maxima de nodos 4 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 5 | static boolean[] vis = new boolean[MAX]; // Marca los nodos ya visitados 6 | static Stack st = new Stack(); 7 | static int[] low = new int[MAX]; 8 | static int[] num = new int[MAX]; 9 | static int compOf[] = new int[MAX]; // Almacena la componente a la que pertenece cada nodo 10 | static int cantSCC; // Cantidad de componentes fuertemente conexas 11 | static int N, M, cont; // Cantidad de nodos y aristas 12 | 13 | static void tarjan(int u) { 14 | low[u] = num[u] = cont++; 15 | st.push(u); 16 | vis[u] = true; 17 | for (int v : g[u]) { 18 | if (num[v] == -1) 19 | tarjan(v); 20 | if (vis[v]) 21 | low[u] = Math.min(low[u], low[v]); 22 | } 23 | if (low[u] == num[u]) { 24 | while (true) { 25 | int v = st.pop(); 26 | vis[v] = false; 27 | compOf[v] = cantSCC; 28 | if (u == v) break; 29 | } 30 | cantSCC++; 31 | } 32 | } 33 | 34 | static void init() { 35 | cont = cantSCC = 0; 36 | for (int i = 0; i <= N; i++) { 37 | g[i].clear(); 38 | num[i] = -1; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /java [outdated]/Graphs/Topological Sort.java: -------------------------------------------------------------------------------- 1 | Dado un grafo acíclico dirigido (DAG), ordena los nodos linealmente de tal manera que si existe una arista entre los nodos u y v entonces u aparece antes que v. 2 | Este ordenamiento es una manera de poner todos los nodos en una línea recta de tal manera que las aristas vayan de izquierda a derecha. 3 | 4 | static final int MAX = 100005; // Cantidad maxima de nodos 5 | static ArrayList g[] = new ArrayList[MAX]; // Lista de adyacencia 6 | static boolean[] vis = new boolean[MAX]; // Marca los nodos ya visitados 7 | static LinkedList topoSort = new LinkedList<>(); // Orden topologico del grafo 8 | static int N, M; // Cantidad de nodos y aristas 9 | 10 | static void dfs(int u) { 11 | vis[u] = true; 12 | for (int v : g[u]) { 13 | if (!vis[v]) dfs(v); 14 | } 15 | topoSort.addFirst(u); 16 | } 17 | 18 | static void init() { 19 | topoSort.clear(); 20 | for (int i = 0; i <= N; i++) { 21 | g[i] = new ArrayList<>(); 22 | vis[i] = false; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /java [outdated]/Math/Binomial Coefficient.java: -------------------------------------------------------------------------------- 1 | Calcula el coeficiente binomial nCr, entendido como el número de subconjuntos de k elementos escogidos de un conjunto con n elementos. 2 | 3 | static long ncr(long n, long r) { 4 | if (r < 0 || n < r) return 0; 5 | r = Math.min(r, n - r); 6 | long ans = 1; 7 | for (int i = 1; i <= r; i++) { 8 | ans = ans * (n - i + 1) / i; 9 | } 10 | return ans; 11 | } 12 | -------------------------------------------------------------------------------- /java [outdated]/Math/Catalan Number.java: -------------------------------------------------------------------------------- 1 | Guarda en el array Catalan Numbers los numeros de Catalan hasta MAX. 2 | 3 | static int MAX = 30; 4 | static long catalan[] = new long[MAX+1]; 5 | 6 | static void catalanNumbers() { 7 | catalan[0] = 1; 8 | for (int i = 1; i <= MAX; i++) { 9 | catalan[i] = (long)(catalan[i-1]*((double)(2*((2 * i)- 1))/(i + 1))); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /java [outdated]/Math/Euler Totient.java: -------------------------------------------------------------------------------- 1 | La función totient de Euler devuelve la cantidad de enteros positivos menores o iguales a n que son coprimos con n (gcd(n, i) = 1) 2 | 3 | * Dado un valor n calcula el Euler totient de n. Debe ejecutarse primero Sieve of Eratosthenes (al menos hasta un numero mayor a la raiz cuadrada de n). 4 | 5 | static long eulerTotient(long n) { 6 | long tot = n; 7 | for (int i = 0, p = primes.get(i); p*p <= n; p = primes.get(++i)) { 8 | if (n % p == 0) { 9 | while (n % p == 0) n /= p; 10 | tot -= tot / p; 11 | } 12 | } 13 | if (n > 1) tot -= tot / n; 14 | return tot; 15 | } 16 | 17 | * Calcular el Euler totient para todos los numeros menores o iguales a MAX. 18 | 19 | static int MAX = 100; 20 | static int[] totient = new int [MAX+1]; 21 | static boolean marked = new boolean[MAX+1]; 22 | 23 | static void eulerTotient() { 24 | marked[1] = 1; 25 | for (int i = 0; i <= MAX; i++) totient[i] = i; 26 | for (int i = 2; i <= MAX; i++) if (!marked[i]) { 27 | for (int j = i; j <= MAX ; j += i) { 28 | totient[j] -= totient[j] / i; 29 | marked[j] = 1; 30 | } 31 | marked[i] = 0; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /java [outdated]/Math/Extended Euclides.java: -------------------------------------------------------------------------------- 1 | El algoritmo de Euclides extendido retorna el gcd(a, b) y calcula los coeficientes enteros X y Y que satisfacen la ecuación: a*X + b*Y = gcd(a, b). 2 | 3 | static int x, y; 4 | // O(log(max(a, b))) 5 | int euclid(int a, int b) { 6 | if (b == 0) { x = 1; y = 0; return a; } 7 | int d = euclid(b, a % b); 8 | int aux = x; 9 | x = y; 10 | y = aux - ((a/b)*y); 11 | return d; 12 | } 13 | -------------------------------------------------------------------------------- /java [outdated]/Math/Gaussian Elimination.java: -------------------------------------------------------------------------------- 1 | Resuelve sistemas de ecuaciones lineales por eliminación Gaussiana. matrix contiene los valores de la matriz cuadrada y result los resultados de las ecuaciones. Retorna un vector con el valor de las n incongnitas. Los resultados pueden necesitar redondeo. 2 | 3 | import java.util.ArrayList; 4 | 5 | static int MAX = 100; 6 | static int n = 3; 7 | static double matrix[][] = new double[MAX][MAX]; 8 | static double result[] = new double[MAX]; 9 | 10 | static ArrayList gauss() { 11 | ArrayList ans = new ArrayList(); 12 | for (int i = 0; i < n; i++) ans.add(0.0); 13 | double temp; 14 | for (int i = 0; i < n; i++) { 15 | int pivot = i; 16 | for (int j = i + 1; j < n; j++) { 17 | temp = Math.abs(matrix[j][i]) - Math.abs(matrix[pivot][i]); 18 | if (temp > 0.000001) pivot = j; 19 | } 20 | double temp2[] = new double[n]; 21 | System.arraycopy(matrix[i], 0, temp2, 0, n); 22 | System.arraycopy(matrix[pivot], 0, matrix[i], 0, n); 23 | System.arraycopy(temp2, 0, matrix[pivot], 0, n); 24 | temp = result[i]; 25 | result[i] = result[pivot]; 26 | result[pivot] = temp; 27 | if (!(Math.abs(matrix[i][i]) < 0.000001)) { 28 | for (int k = i + 1; k < n; k++) { 29 | temp = -matrix[k][i] / matrix[i][i]; 30 | matrix[k][i] = 0; 31 | for (int l = i + 1; l < n; l++) { 32 | matrix[k][l] += matrix[i][l] * temp; 33 | } 34 | result[k] += result[i] * temp; 35 | } 36 | } 37 | } 38 | for (int m = n - 1; m >= 0; m--) { 39 | temp = result[m]; 40 | for (int i = n - 1; i > m; i--) { 41 | temp -= ans.get(i) * matrix[m][i]; 42 | } 43 | ans.set(m, temp / matrix[m][m]); 44 | } 45 | return ans; 46 | } 47 | -------------------------------------------------------------------------------- /java [outdated]/Math/Greatest common divisor.java: -------------------------------------------------------------------------------- 1 | Calcula el máximo común divisor entre a y b mediante el algoritmo de Euclides 2 | 3 | public static int gcd(int a, int b) { 4 | if (b == 0) { 5 | return a; 6 | } 7 | return gcd(b, a % b); 8 | } 9 | -------------------------------------------------------------------------------- /java [outdated]/Math/Lowest Common multiple.java: -------------------------------------------------------------------------------- 1 | Calculo del mínimo común múltiplo usando el máximo común divisor. Agregar Greatest Common Divisor. 2 | 3 | public static int lcm(int a, int b) { 4 | return a * b / gcd(a, b); 5 | } 6 | -------------------------------------------------------------------------------- /java [outdated]/Math/Miller-Rabin.java: -------------------------------------------------------------------------------- 1 | La función de Miller-Rabin determina si un número dado es o no un número primo. IMPORTANTE: Debe agregarse los métodos de Modular Exponentiation y Modular Multiplication. 2 | 3 | public static boolean isPrime(long p) { 4 | if (p < 2 || (p != 2 && p % 2 == 0)) { 5 | return false; 6 | } 7 | long s = p - 1; 8 | while (s % 2 == 0) { 9 | s /= 2; 10 | } 11 | for (int i = 0; i < 5; i++) { 12 | long a = (long) (Math.random() * p) % (p - 1) + 1; 13 | long temp = s; 14 | long mod = modpow(a, temp, p); 15 | while (temp != p - 1 && mod != 1 && mod != p - 1) { 16 | mod = modmul(mod, mod, p); 17 | temp *= 2; 18 | } 19 | if (mod != p - 1 && temp % 2 == 0) { 20 | return false; 21 | } 22 | } 23 | return true; 24 | } 25 | -------------------------------------------------------------------------------- /java [outdated]/Math/Mobius.java: -------------------------------------------------------------------------------- 1 | La función mu de Mobius devuelve 0 si n es divisible por algún cuadrado. 2 | Si n es libre de cuadrados entonces devuelve 1 o -1 si n tiene un número par o impar de factores primos distintos. 3 | * Calcular Mobius para todos los numeros menores o iguales a MAX con Sieve of Eratosthenes. 4 | 5 | static final int MAX = 1000000; 6 | static short mu[] = new short [MAX+1]; 7 | 8 | // O(MAX log(log(MAX))) 9 | static void mobius() { 10 | mu[0] = 0; mu[1] = 1; 11 | for (int i = 1; i <= MAX; i++) if (mu[i]==1) { 12 | for (int j = i+i; j <= MAX; j += i) { 13 | mu[j] -= mu[i]; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /java [outdated]/Math/Pollard Rho.java: -------------------------------------------------------------------------------- 1 | La función Rho de Pollard calcula un divisor no trivial de n. 2 | IMPORTANTE: Deben agregarse Modular Multiplication y Greatest common divisor para long. 3 | 4 | public static long rho(long n) { 5 | if ((n&1)==0) return 2; 6 | long i = 0, k = 2, x = 3, y = 3, d; 7 | while (true) { 8 | x = (modmul(x, x, n) + n - 1) % n; 9 | d = gcd(Math.abs(y - x), n); 10 | if (d != 1 && d != n) return d; 11 | if (++i == k) { y = x; k <<= 1; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /java [outdated]/Math/Prime Factorization.java: -------------------------------------------------------------------------------- 1 | Guarda en factors la lista de factores primos de n de menor a mayor. IMPORTANTE: Debe ejecutarse primero Sieve of Eratosthenes (al menos hasta un numero mayor a la raiz cuadrada de n). 2 | 3 | static ArrayList factors = new ArrayList<>(); 4 | 5 | public static void primeFactors(long n) { 6 | factors.clear(); 7 | for (int i = 0, p = primes.get(i); p*p <= n; p = primes.get(++i)) { 8 | while (n % p == 0) { 9 | factors.add(p); 10 | n /= p; 11 | } 12 | } 13 | if (n > 1) factors.add(n); 14 | } 15 | -------------------------------------------------------------------------------- /java [outdated]/Math/Sieve of Eratosthenes.java: -------------------------------------------------------------------------------- 1 | Guarda en primes los números primos menores o iguales a MAX. Para saber si p es un número primo, hacer: if (!marked[p]) 2 | 3 | static int MAX = 1000000; 4 | static int SQRT = 1000; 5 | static ArrayList primes = new ArrayList<>(); 6 | static boolean marked[] = new boolean[MAX+1]; 7 | 8 | static void sieve() { 9 | marked[1] = true; 10 | int i = 2; 11 | for (; i <= SQRT; ++i) if (!marked[i]) { 12 | primes.add(i); 13 | for (int j = i*i; j <= MAX; j += i) marked[j] = true; 14 | } 15 | for (; i <= MAX; ++i) if (!marked[i]) primes.add(i); 16 | } 17 | -------------------------------------------------------------------------------- /java [outdated]/Modular arithmetic/Chinese Remainder Theorem.java: -------------------------------------------------------------------------------- 1 | Encuentra un x tal que para cada i : x es congruente con A_i mod M_i 2 | Devuelve un vector con dos posiciones donde [0] = x && [1] = lcm 3 | donde x es la solución con modulo lcm (lcm = LCM(M_0, M_1, ...)). Dado un k : x + k*lcm es solución tambien. 4 | Si la solución no existe o la entrada no es válida devuelve {-1, -1} 5 | --> Agregar Extended Euclides <-- 6 | 7 | static int[] crt(ArrayList A, ArrayList M) { 8 | int n = A.size(), ans = A.get(0), lcm = M.get(0); 9 | for (int i = 1; i < n; i++) { 10 | int d = euclid(lcm, M.get(i)); 11 | if (((A.get(i) - ans) % d) == 1) { int y[] = {-1, -1}; return y; }; 12 | int mod = lcm / d * M.get(i); 13 | ans = (ans + x * (A.get(i) - ans) / d % (M.get(i) / d) * lcm) % mod; 14 | if (ans < 0) ans += mod; 15 | lcm = mod; 16 | } 17 | int y[] = {ans, lcm}; 18 | return y; 19 | } 20 | -------------------------------------------------------------------------------- /java [outdated]/Modular arithmetic/Fibonacci mod m.java: -------------------------------------------------------------------------------- 1 | Calcula fibonacci(n) % m. 2 | 3 | static long fib(long n, long m) { 4 | long a = 0, b = 1, c; 5 | int log2 = (int) (Math.log(n) / Math.log(2)); 6 | for (int i = log2; i >= 0; i--) { 7 | c = a; 8 | a = ((c%m) * (2*(b%m) - (c%m) + m)) % m; 9 | b = ((c%m) * (c%m) + (b%m) * (b%m)) % m; 10 | if (((n >> i) & 1) != 0) { 11 | c = (a + b) % m; 12 | a = b; b = c; 13 | } 14 | } 15 | return a; 16 | } 17 | -------------------------------------------------------------------------------- /java [outdated]/Modular arithmetic/Modular Exponentiation.java: -------------------------------------------------------------------------------- 1 | Realiza la operación (a ^ b) % mod. 2 | 3 | static long modpow(long a, long b, long mod) { 4 | if (b == 0) return 1; 5 | if (b % 2 == 0) { 6 | long temp = modpow(a, b/2, mod); 7 | return (temp * temp) % mod; 8 | } else { 9 | long temp = modpow(a, b-1, mod); 10 | return (temp * a) % mod; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /java [outdated]/Modular arithmetic/Modular Inverse.java: -------------------------------------------------------------------------------- 1 | El inverso multiplicativo modular de a % mod es un entero b tal que (a*b) % mod = 1. Éste existe siempre y cuando a y mod sean coprimos (gcd(a, mod) = 1). 2 | El inverso modular de a se utiliza para calcular (n/a) % mod como (n*b) % mod. 3 | 4 | * Se puede calcular usando el algoritmo de Euclides extendido. Agregar Extended Euclides. 5 | 6 | public static long modInverse(int a, int mod) { 7 | long d = extendedEuclid(a, mod); 8 | if (d > 1) { 9 | return -1; 10 | } 11 | return (x % mod + mod) % mod; 12 | } 13 | 14 | * Si mod es un número primo, se puede calcular aplicando el pequeño teorema de Fermat. Agregar Modular Exponentiation. 15 | 16 | public static long modInverse(int a, int mod) { 17 | return modpow(a, mod - 2, mod); 18 | } 19 | 20 | * Calcular el inverso modular para todos los numeros menores a mod. 21 | 22 | static int inv[]; 23 | 24 | public static void modInverse(int mod) { 25 | inv = new int[mod]; 26 | inv[1] = 1; 27 | for (int i = 2; i < mod; i++) { 28 | inv[i] = (mod - (mod / i) * inv[mod % i] % mod) % mod; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /java [outdated]/Modular arithmetic/Modular Multiplication.java: -------------------------------------------------------------------------------- 1 | Realiza la operación (a * b) % mod minimizando posibles desbordamientos. 2 | 3 | public static long modmul(long a, long b, long mod) { 4 | long x = 0; 5 | long y = a % mod; 6 | while (b > 0) { 7 | if (b % 2 == 1) { 8 | x = (x + y) % mod; 9 | } 10 | y = (y << 1) % mod; 11 | b >>= 1; 12 | } 13 | return x % mod; 14 | } 15 | -------------------------------------------------------------------------------- /java [outdated]/Modular arithmetic/Pisano Period.java: -------------------------------------------------------------------------------- 1 | Calcula el Periodo de Pisano de m, que es el periodo con el cual se repite la Sucesión de Fibonacci modulo m. 2 | IMPORTANTE: Si m es primo el algoritmo funciona (considerable) para m < 10^6. Debe agregarse Modular Exponentiation (sin el modulo) y Lowest Common Multiple (para long). 3 | 4 | static long period(long m) { 5 | long a = 0, b = 1, c, pp = 0; 6 | do { 7 | c = (a + b) % m; 8 | a = b; b = c; pp++; 9 | } while (a != 0 || b != 1); 10 | return pp; 11 | } 12 | 13 | static long pisanoPrime(long p, long e) { 14 | return modpow(p, e-1) * period(p); 15 | } 16 | 17 | static long pisanoPeriod(long m) { 18 | long pp = 1; 19 | for (long p = 2; p*p <= m; p++) { 20 | if (m % p == 0) { 21 | long e = 0; 22 | while (m % p == 0) { 23 | e++; 24 | m /= p; 25 | } 26 | pp = lcm(pp, pisanoPrime(p, e)); 27 | } 28 | } 29 | if (m > 1) pp = lcm(pp, period(m)); 30 | return pp; 31 | } 32 | -------------------------------------------------------------------------------- /java [outdated]/Strings/KMP's Algorithm.java: -------------------------------------------------------------------------------- 1 | Encuentra si el string pattern se encuentra en el string cadena. Debe estar definido el método prefix_function. 2 | 3 | import java.util.ArrayList; 4 | 5 | static boolean kmp(String cadena, String pattern) { 6 | int n=cadena.length(); 7 | int m=pattern.length(); 8 | ArrayList tab=prefix_function(pattern); 9 | 10 | for (int i = 0, seen = 0; i < n; i++) { 11 | while (seen > 0 && cadena.charAt(i) != pattern.charAt(seen)) { 12 | seen = tab.get(seen-1); 13 | } 14 | if (cadena.charAt(i) == pattern.charAt(seen)) seen++; 15 | if (seen == m) return true; 16 | } 17 | return false; 18 | } 19 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Prefix Function.java: -------------------------------------------------------------------------------- 1 | Dado un string s retorna un array pf donde pf[i] es el largo del prefijo propio más largo 2 | que tambien es sufijo de cad[0] hasta cad[i]. 3 | El String debe pasarse como un array de chars cadena.toCharArray(); 4 | // O(n) 5 | 6 | static int[] prefix_function(char[] cad) { 7 | int n = cad.length; 8 | int pf[] = new int[n]; 9 | pf[0] = 0; 10 | for (int i = 1, j = 0; i < n; i++) { 11 | while (j==1 && cad[i] != cad[j]) j = pf[j-1]; 12 | if (cad[i] == cad[j]) j++; 13 | pf[i] = j; 14 | } 15 | return pf; 16 | } 17 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Prefix-Function.java: -------------------------------------------------------------------------------- 1 | Dado un string s retorna un ArrayList lps donde lps[i] es el largo del prefijo propio más largo que tambien es sufijo de s[0] hasta s[i]. 2 | *Para retornar el vector de suffix_link quitar el comentario (//). 3 | 4 | static ArrayList prefix_function(String s) { 5 | int n = s.length(), len = 0, i = 1; 6 | ArrayList lps = new ArrayList<>(); 7 | Collections.fill(lps, n); 8 | lps.set(len, 0); 9 | while (i < n) { 10 | if (s.charAt(len) != s.charAt(i)) { 11 | if (len > 0) len = lps.get(len-1); 12 | else lps.set(i++, len); 13 | } else lps.set(i++, ++len); 14 | } 15 | // lps.add(0, -1); // Para SuffixLink 16 | return lps; 17 | } 18 | -------------------------------------------------------------------------------- /java [outdated]/Strings/String Hashing.java: -------------------------------------------------------------------------------- 1 | Estructura para realizar operaciones de hashing. 2 | 3 | static long p[] = {257, 359}; 4 | static long mod[] = {1000000007, 1000000009}; 5 | static long X = 1000000010; 6 | 7 | static class Hashing { 8 | long[][] h, pot; 9 | int n; 10 | 11 | public Hashing(String _s) { 12 | char[] s = _s.toCharArray(); 13 | n = s.length; 14 | h = new long[2][n + 1]; 15 | pot = new long[2][n + 1]; 16 | 17 | for (int i = 0; i < 2; ++i) { 18 | pot[i][0] = 1; 19 | } 20 | for (int i = 1; i <= n; ++i) { 21 | for (int j = 0; j < 2; ++j) { 22 | h[j][i] = (h[j][i-1] * p[j] + s[i-1]) % mod[j]; 23 | pot[j][i] = (pot[j][i-1] * p[j]) % mod[j]; 24 | } 25 | } 26 | } 27 | // Hash del substring en el rango [i, j) 28 | long hash(int i, int j) { 29 | long a = (h[0][j] - (h[0][i] * pot[0][j-i] % mod[0]) + mod[0]) % mod[0]; 30 | long b = (h[1][j] - (h[1][i] * pot[1][j-i] % mod[1]) + mod[1]) % mod[1]; 31 | return a*X + b; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Suffix Array Init.java: -------------------------------------------------------------------------------- 1 | Crea el suffix array. Deben inicializarse las variables s (String original), N_MAX (Máximo size que puede tener s), y n (Size del string actual). 2 | 3 | static String s; 4 | static int N_MAX = 30; 5 | static int n; 6 | static char _s[]; 7 | static int sa[] = new int[N_MAX]; 8 | static int rk[] = new int[N_MAX]; 9 | static long rk2[] = new long[N_MAX]; 10 | 11 | static List wrapper = new AbstractList() { 12 | @Override 13 | public Integer get(int i) { return sa[i]; } 14 | 15 | @Override 16 | public int size() { return n; } 17 | 18 | @Override 19 | public Integer set(int i, Integer e) { 20 | int v = sa[i]; 21 | sa[i] = e; 22 | return v; 23 | } 24 | }; 25 | 26 | static void suffixArray() { 27 | _s = s.toCharArray(); 28 | for (int i = 0; i < n; i++) { 29 | sa[i] = i; rk[i] = _s[i]; rk2[i] = 0; 30 | } 31 | for (int l = 1; l < n; l <<= 1) { 32 | for (int i = 0; i < n; i++) { 33 | rk2[i] = ((long) rk[i] << 32) + (i + l < n ? rk[i + l] : -1); 34 | } 35 | Collections.sort(wrapper, new Comparator() { 36 | @Override 37 | public int compare(Integer o1, Integer o2) { 38 | if (rk2[o1.intValue()] > rk2[o2.intValue()]) return 1; 39 | else if (rk2[o1.intValue()] == rk2[o2.intValue()]) return 0; 40 | else return -1; 41 | } 42 | }); 43 | for (int i = 0; i < n; i++) { 44 | if (i > 0 && rk2[sa[i]] == rk2[sa[i - 1]]) 45 | rk[sa[i]] = rk[sa[i - 1]]; 46 | else rk[sa[i]] = i; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Suffix Array Longest Common Prefix.java: -------------------------------------------------------------------------------- 1 | Calcula el array Longest Common Prefix para todo el suffix array. IMPORTANTE: Debe haberse ejecutado primero suffixArray(), incluido en Suffix Array Init.java 2 | 3 | static int lcp[] = new int[N_MAX]; 4 | 5 | static void calculateLCP() { 6 | for (int i = 0, l = 0; i < n; i++) { 7 | if (rk[i] > 0) { 8 | int j = sa[rk[i] - 1]; 9 | while (_s[i + l] == _s[j + l]) l++; 10 | lcp[rk[i]] = l; 11 | if (l > 0) l--; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Suffix Array Longest Common Substring.java: -------------------------------------------------------------------------------- 1 | Busca el substring común mas largo entre dos strings. Retorna un int[2], con el size del substring y uno de los indices del suffix array. Debe ejecutarse previamente suffixArray() y calculateLCP() 2 | 3 | // Los substrings deben estar concatenados de la forma "string1#string2$", antes de ejecutar suffixArray() y calculateLCS() 4 | // m debe almacenar el size del string2. 5 | 6 | static int[] longestCommonSubstring() { 7 | int i, ans[] = new int[2]; 8 | ans[0] = -1; ans[1] = 0; 9 | for (i = 1; i < n; i++) { 10 | if (((sa[i] < n - m - 1) != (sa[i - 1] < n - m - 1)) && lcp[i] > ans[0]) { 11 | ans[0] = lcp[i]; ans[1] = i; 12 | } 13 | } 14 | return ans; 15 | } 16 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Suffix Array Longest Repeated Substring.java: -------------------------------------------------------------------------------- 1 | Retorna un int[] con el size y el indice del suffix array en el cual se encuentra el substring repetido mas largo. Debe ejecutarse primero suffixArray() y calculateLCP(). 2 | 3 | static int[] longestRepeatedSubstring() { 4 | int ans[] = new int[2]; ans[0] = -1; ans[1] = -1; 5 | for (int i = 0; i < n; i++) { 6 | if (ans[0] < lcp[i]) { 7 | ans[0] = lcp[i]; ans[1] = i; 8 | } 9 | } 10 | return ans; 11 | } 12 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Suffix Array String Matching Boolean.java: -------------------------------------------------------------------------------- 1 | Busca el string p en el string s (definido en init), y retorna true si se encuentra, o false en caso contrario. Debe inicializarse m con el tamaño de p, y debe ejecutarse previamente suffixArray() de Suffix Array Init.java. 2 | 3 | static String p; 4 | static int m; 5 | 6 | static boolean stringMatching() { 7 | if (m - 1 > n) return false; 8 | char [] _p = p.toCharArray(); 9 | int l = 0, h = n - 1, c = l; 10 | while (l <= h) { 11 | c = (l + h) / 2; 12 | int r = strncmp(_s, sa[c], _p); 13 | if (r > 0) h = c - 1; 14 | else if (r < 0) l = c + 1; 15 | else return true; 16 | } 17 | return false; 18 | } 19 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Suffix Array String Matching.java: -------------------------------------------------------------------------------- 1 | Busca el string p en el string s (definido en init), y retorna un int[2] con el primer y ultimo indice del suffix array que coinciden con la busqueda. Si no se encuentra, retorna [-1, -1]. Debe inicializarse m con el tamaño de p, y debe ejecutarse previamente suffixArray() de Suffix Array Init.java. 2 | 3 | static String p; 4 | static int m; 5 | 6 | static int[] stringMatching() { 7 | int[] ans = {-1, -1}; 8 | if (m - 1 > n) return ans; 9 | char [] _p = p.toCharArray(); 10 | int l = 0, h = n - 1, c = l; 11 | while (l < h) { 12 | c = (l + h) / 2; 13 | if (strncmp(_s, sa[c], _p) >= 0) h = c; 14 | else l = c + 1; 15 | } 16 | if (strncmp(_s, sa[l], _p) != 0) return ans; 17 | ans[0] = l; 18 | l = 0; h = n - 1; c = l; 19 | while (l < h) { 20 | c = (l + h) / 2; 21 | if (strncmp(_s, sa[c], _p) > 0) h = c; 22 | else l = c + 1; 23 | } 24 | if (strncmp(_s, sa[h], _p) != 0) h--; 25 | ans[1] = h; 26 | return ans; 27 | } 28 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Suffix Array strncmp.java: -------------------------------------------------------------------------------- 1 | Método utilitario. Necesario para las dos versiones de Matching. 2 | 3 | static int strncmp(char[] a, int i, char[] b) { 4 | for (int k = 0; i + k < a.length && k < m - 1; k++) { 5 | if (a[i + k] != b[k]) return a[i + k] - b[k]; 6 | } 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Trie.java: -------------------------------------------------------------------------------- 1 | (Prefix tree) Estructura de datos para almacenar un diccionario de strings. Debe ejecutarse el método init_trie. El método dfs hace un recorrido en orden del trie. 2 | 3 | import java.util.*; 4 | 5 | class Main { 6 | static int MAX_L = 26; // cantidad de letras del lenguaje 7 | static char L = 'a'; // primera letra del lenguaje 8 | static ArrayList trie; 9 | 10 | static class node { 11 | Integer next[]; 12 | boolean fin; 13 | 14 | public node() { 15 | next = new Integer[MAX_L]; 16 | this.fin = false; 17 | } 18 | } 19 | 20 | static void init_trie() { 21 | trie = new ArrayList<>(); 22 | trie.add(new node()); 23 | } 24 | 25 | static void add_str(String s) { 26 | int cur = 0, c; 27 | for (int i = 0; i < s.length(); i++) { 28 | c = s.charAt(i) - L; 29 | if (trie.get(cur).next[c] == null) { 30 | trie.get(cur).next[c] = trie.size(); 31 | trie.add(new node()); 32 | } 33 | cur = trie.get(cur).next[c]; 34 | } 35 | trie.get(cur).fin = true; 36 | } 37 | 38 | static boolean contain(String s) { 39 | int cur = 0, c; 40 | for (int i = 0; i < s.length(); i++) { 41 | c = s.charAt(i) - L; 42 | if (trie.get(cur).next[c] == null) return false; 43 | cur = trie.get(cur).next[c]; 44 | } 45 | return trie.get(cur).fin; 46 | } 47 | 48 | static void dfs(int cur) { 49 | for (int i = 0; i < MAX_L; ++i) { 50 | if (trie.get(cur).next[i] != null) { 51 | // System.out.println((char)(i+L)); 52 | dfs(trie.get(cur).next[i]); 53 | } 54 | } 55 | } 56 | 57 | public static void main(String[] args) { 58 | init_trie(); 59 | String s[] = {"hello", "world", "help"}; 60 | for (String c : s) add_str(c); 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /java [outdated]/Strings/Z-Function.java: -------------------------------------------------------------------------------- 1 | Dado un string s retorna un arreglo z donde z[i] es igual al mayor numero de caracteres desde s[i] que coinciden con los caracteres desde s[0] 2 | 3 | static int[] z_function(String ss) { 4 | StringBuilder s = new StringBuilder(ss); 5 | int n = s.length(); 6 | int[] z = new int[n]; 7 | for (int i = 1, x = 0, y = 0; i < n; i++) { 8 | z[i] = Math.max(0, Math.min(z[i - x], y - i + 1)); 9 | while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i])) { 10 | x = i; y = i + z[i]; z[i]++; 11 | } 12 | } 13 | return z; 14 | } 15 | -------------------------------------------------------------------------------- /java [outdated]/Utilities/Binary search.java: -------------------------------------------------------------------------------- 1 | Dado un arreglo ordenado ascendentemente de tamaño n, busca el elemento x y devuelve su posición, si no lo encuentra devuelve -1. 2 | 3 | static int binary_search(int array[], int x) { 4 | int l = 0, r = arr.length-1; 5 | while (l <= r) { 6 | int m = (l+r)/2; 7 | if (array[m] < x) l = m+1; 8 | else if (array[m] > x) r = m-1; 9 | else return m; 10 | } 11 | return -1; 12 | } 13 | -------------------------------------------------------------------------------- /java [outdated]/Utilities/Biseccion.java: -------------------------------------------------------------------------------- 1 | Método de bisección para una función f(m) 2 | 3 | static double eps = 0.0000001; 4 | 5 | static double bis(double a, double b) { 6 | double m = (a+b)/2; 7 | if (Math.abs(f(m)) < eps) return m; 8 | if (f(a) * f(m) < 0) return bis(a, m); 9 | return bis(m, b); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /java [outdated]/Utilities/Bit Manipulation.java: -------------------------------------------------------------------------------- 1 | Operaciones a nivel de bits. 2 | 3 | n & 1 -> Verifica si n es impar o no 4 | n & (1< Verifica si el k-esimo bit esta encendido o no 5 | n | (1< Enciende el k-esimo bit 6 | n & ~(1< Apaga el k-esimo bit 7 | n ^ (1< Invierte el k-esimo bit 8 | ~n -> Invierte todos los bits 9 | n & -n -> Devuelve el bit encendido mas a la derecha 10 | ~n & (n+1) -> Devuelve el bit apagado mas a la derecha 11 | n | (n+1) -> Enciende el bit apagado mas a la derecha 12 | n & (n-1) -> Apaga el bit encendido mas a la derecha 13 | -------------------------------------------------------------------------------- /java [outdated]/Utilities/Lower bound.java: -------------------------------------------------------------------------------- 1 | Dado un arreglo ordenado ascendentemente de tamaño n, busca el elemento x y devuelve la posición de la primera aparición de x, si no lo encuentra devuelve la siguiente posición. Si la posición se sale del arreglo devuelve -1. 2 | 3 | static int lower_bound(int arr[], int x) { 4 | int l = 0, r = arr.length-1; 5 | if (arr[r] < x) return -1; 6 | while (l < r) { 7 | int m = (l+r)/2; 8 | if (arr[m] < x) l = m+1; 9 | else r = m; 10 | } 11 | return l; 12 | } 13 | -------------------------------------------------------------------------------- /java [outdated]/Utilities/Optimized Scanner.java: -------------------------------------------------------------------------------- 1 | Libreria para recibir las entradas; reemplaza el Scanner original, mejorando su eficiencia. 2 | Contiene los metodos next, nextLine y hasNext. Para recibir datos numericos parsear el string leido. 3 | 4 | static class Scanner { 5 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 6 | StringTokenizer st = new StringTokenizer(""); 7 | int spaces = 0; 8 | 9 | public String nextLine() throws IOException { 10 | if (spaces-- > 0) return ""; 11 | else if (st.hasMoreTokens()) return new StringBuilder(st.nextToken("\n")).toString(); 12 | return br.readLine(); 13 | } 14 | 15 | public String next() throws IOException { 16 | spaces = 0; 17 | while (!st.hasMoreTokens()) st = new StringTokenizer(br.readLine()); 18 | return st.nextToken(); 19 | } 20 | 21 | public boolean hasNext() throws IOException { 22 | while (!st.hasMoreTokens()) { 23 | String line = br.readLine(); 24 | if (line == null) return false; 25 | if (line.equals("")) spaces = Math.max(spaces, 0) + 1; 26 | st = new StringTokenizer(line); 27 | } 28 | return true; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /java [outdated]/Utilities/Template.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.lang.*; 3 | import java.io.*; 4 | import java.math.*; 5 | 6 | class Main { 7 | 8 | static Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in))); 9 | static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); 10 | 11 | public static void main(String[] args) { 12 | // Tu código... 13 | int a = Integer.parseInt(in.next()); 14 | int b = Integer.parseInt(in.next()); 15 | double c = a + b; 16 | // Para imprimir con 6 decimales 17 | // Locale.setDefault(Locale.US); 18 | // out.printf("%.6f\n", c); 19 | out.println(c); 20 | out.close(); // Obligatorio al finalizar el programa 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /java [outdated]/Utilities/Ternary Search.java: -------------------------------------------------------------------------------- 1 | Retorna el valor minimo de una funcion entre l y r. Se recomienda usar 50 iteraciones. 2 | 3 | static double f(double x) { 4 | return // funcion a evaluar que depende de x 5 | } 6 | 7 | static double ternary_search(double l, double r, int it) { 8 | double a = (2.0*l + r)/3.0; 9 | double b = (l + 2.0*r)/3.0; 10 | if (it == 0) return f(a); 11 | if (f(a) < f(b)) return ternary_search(l, b, it-1); 12 | return ternary_search(a, r, it-1); 13 | } 14 | -------------------------------------------------------------------------------- /java [outdated]/Utilities/Upper bound.java: -------------------------------------------------------------------------------- 1 | Dado un arreglo ordenado ascendentemente de tamaño n, busca el elemento x y devuelve la posición siguiente a la ultima aparición de x. Si la posición se sale del arreglo devuelve -1. 2 | 3 | static int upper_bound(int arr[], int x) { 4 | int l = 0, r = arr.length-1; 5 | if (arr[r] <= x) return -1; 6 | while (l < r) { 7 | int m = (l+r)/2; 8 | if (arr[m] <= x) l = m+1; 9 | else r = m; 10 | } 11 | return l; 12 | } 13 | -------------------------------------------------------------------------------- /java [outdated]/Values sequences and results/ASCII Table.tex: -------------------------------------------------------------------------------- 1 | Caracteres ASCII con sus respectivos valores numéricos. 2 | 3 | 4 | \begin{tabbing} 5 | \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \= \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \\ 6 | 0 \> NUL \> 16 \> DLE \\ 7 | 1 \> SOH \> 17 \> DC1 \\ 8 | 2 \> STX \> 18 \> DC2 \\ 9 | 3 \> ETX \> 19 \> DC3 \\ 10 | 4 \> EOT \> 20 \> DC4 \\ 11 | 5 \> ENQ \> 21 \> NAK \\ 12 | 6 \> ACK \> 22 \> SYN \\ 13 | 7 \> BEL \> 23 \> ETB \\ 14 | 8 \> BS \> 24 \> CAN \\ 15 | 9 \> TAB \> 25 \> EM \\ 16 | 10 \> LF \> 26 \> SUB \\ 17 | 11 \> VT \> 27 \> ESC \\ 18 | 12 \> FF \> 28 \> FS \\ 19 | 13 \> CR \> 29 \> GS \\ 20 | 14 \> SO \> 30 \> RS \\ 21 | 15 \> SI \> 31 \> US \\ 22 | \end{tabbing} 23 | 24 | 25 | \begin{tabbing} 26 | \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \= \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \\ 27 | 32 \> (space) \> 48 \> 0 \\ 28 | 33 \> ! \> 49 \> 1 \\ 29 | 34 \> " \> 50 \> 2 \\ 30 | 35 \> \# \> 51 \> 3 \\ 31 | 36 \> \$ \> 52 \> 4 \\ 32 | 37 \> \% \> 53 \> 5 \\ 33 | 38 \> \& \> 54 \> 6 \\ 34 | 39 \> ' \> 55 \> 7 \\ 35 | 40 \> ( \> 56 \> 8 \\ 36 | 41 \> ) \> 57 \> 9 \\ 37 | 42 \> * \> 58 \> : \\ 38 | 43 \> + \> 59 \> ; \\ 39 | 44 \> , \> 60 \> < \\ 40 | 45 \> - \> 61 \> = \\ 41 | 46 \> . \> 62 \> > \\ 42 | 47 \> / \> 63 \> ? \\ 43 | \end{tabbing} 44 | 45 | \begin{tabbing} 46 | \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \= \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \\ 47 | 64 \> @ \> 80 \> P \\ 48 | 65 \> A \> 81 \> Q \\ 49 | 66 \> B \> 82 \> R \\ 50 | 67 \> C \> 83 \> S \\ 51 | 68 \> D \> 84 \> T \\ 52 | 69 \> E \> 85 \> U \\ 53 | 70 \> F \> 86 \> V \\ 54 | 71 \> G \> 87 \> W \\ 55 | 72 \> H \> 88 \> X \\ 56 | 73 \> I \> 89 \> Y \\ 57 | 74 \> J \> 90 \> Z \\ 58 | 75 \> K \> 91 \> [ \\ 59 | 76 \> L \> 92 \> \textbackslash \\ 60 | 77 \> M \> 93 \> ] \\ 61 | 78 \> N \> 94 \> \textasciicircum \\ 62 | 79 \> O \> 95 \> \_ \\ 63 | \end{tabbing} 64 | 65 | \begin{tabbing} 66 | \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \= \textbf{No.}\hspace{1cm} \= \textbf{ASCII}\hspace{2cm} \\ 67 | 96 \> ` \> 112 \> p \\ 68 | 97 \> a \> 113 \> q \\ 69 | 98 \> b \> 114 \> r \\ 70 | 99 \> c \> 115 \> s \\ 71 | 100 \> d \> 116 \> t \\ 72 | 101 \> e \> 117 \> u \\ 73 | 102 \> f \> 118 \> v \\ 74 | 103 \> g \> 119 \> w \\ 75 | 104 \> h \> 120 \> x \\ 76 | 105 \> i \> 121 \> y \\ 77 | 106 \> j \> 122 \> z \\ 78 | 107 \> k \> 123 \> \{ \\ 79 | 108 \> l \> 124 \> \textbar \\ 80 | 109 \> m \> 125 \> \} \\ 81 | 110 \> n \> 126 \> \textasciitilde \\ 82 | 111 \> o \> 127 \> \\ 83 | \end{tabbing} 84 | -------------------------------------------------------------------------------- /java [outdated]/Values sequences and results/Sequences.tex: -------------------------------------------------------------------------------- 1 | Listado de secuencias mas comunes y como hallarlas. 2 | 3 | \begin{center} 4 | \tablefirsthead{} 5 | \tabletail{ 6 | \midrule 7 | \multicolumn{2}{r}{{Continúa en la siguiente columna}} \\} 8 | \tablelasttail{} 9 | {\renewcommand{\arraystretch}{1.4} 10 | \begin{supertabular}{|p{1.8cm}|p{8.6cm}|} 11 | 12 | \hline 13 | 14 | \multirow{2}{2cm}{Estrellas octangulares} 15 | & 0, 1, 14, 51, 124, 245, 426, 679, 1016, 1449, 1990, 2651, ... 16 | \\ \cline{2-2} 17 | & $f(n) = n*(2*n^{2} - 1)$. 18 | \\ \hline 19 | 20 | 21 | \multirow{2}{2cm} 22 | {Euler totient} 23 | & 1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6,... 24 | \\ \cline{2-2} 25 | & $f(n) = $ Cantidad de números naturales $\leq n$ coprimos con n. 26 | \\ \hline 27 | 28 | \multirow{2}{2cm}{Números de Bell} 29 | & 1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, ... 30 | \\ \cline{2-2} 31 | & Se inicia una matriz triangular con f[0][0] = f[1][0] = 1. La suma de estos dos se guarda en f[1][1] y se traslada a f[2][0]. Ahora se suman f[1][0] con f[2][0] y se guarda en f[2][1]. Luego se suman f[1][1] con f[2][1] y se guarda en f[2][2] trasladandose a f[3][0] y así sucesivamente. Los valores de la primera columna contienen la respuesta. 32 | \\ \hline 33 | 34 | 35 | \multirow{2}{2cm} 36 | {Números de Catalán} 37 | & 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, ... 38 | \\ \cline{2-2} 39 | & $f(n)=\displaystyle\frac{(2n)!}{(n + 1)! n!}$ 40 | 41 | \\ \hline 42 | 43 | \multirow{2}{2cm}{Números de Fermat} 44 | & 3, 5, 17, 257, 65537, 4294967297, 18446744073709551617, ... 45 | \\ \cline{2-2} 46 | & $f(n) = 2^{(\displaystyle2^{\textstyle n})} + 1$ 47 | \\ \hline 48 | 49 | 50 | \multirow{2}{2cm} 51 | {Números de Fibonacci} 52 | & 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ... 53 | \\ \cline{2-2} 54 | & $f(0) = 0$; $f(1) = 1$; $f(n) = f(n-1) + f(n-2)$ para $n>1$ \\ \hline 55 | 56 | \multirow{2}{2cm} 57 | {Números de Lucas} 58 | & 2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199, 322, ... 59 | \\ \cline{2-2} 60 | & $f(0) = 2$; $f(1) = 1$; $f(n) = f(n-1) + f(n-2)$ para $n>1$ 61 | \\ \hline 62 | 63 | \multirow{2}{2cm}{Números de Pell} 64 | & 0, 1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, ... 65 | \\ \cline{2-2} 66 | & $f(0) = 0; f(1) = 1; f(n) = 2f(n-1) + f(n-2)$ para $n>1$ 67 | \\ \hline 68 | 69 | \multirow{2}{2cm} 70 | {Números de Tribonacci} 71 | & 0, 0, 1, 1, 2, 4, 7, 13, 24, 44, 81, 149, 274, 504, ... 72 | \\ \cline{2-2} 73 | & $f(0)=f(1)=0; f(2)=1; f(n) = f(n-1) + f(n-2) + f(n-3)$ para $n>2$ 74 | \\ \hline 75 | 76 | \multirow{2}{2cm}{Números factoriales} 77 | & 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, ... 78 | \\ \cline{2-2} 79 | &$ f(0) = 1; f(n) = \displaystyle\prod_{\textstyle k=1}^{\textstyle n}k$ para $n>0$. 80 | 81 | \\ \hline 82 | 83 | \multirow{2}{2cm}{Números piramidales cuadrados} 84 | & 0, 1, 5, 14, 30, 55, 91, 140, 204, 285, 385, 506, 650, ... 85 | \\ \cline{2-2} 86 | & $f(n) = \displaystyle\frac{n*(n+1)*(2*n+1)}{6}$ 87 | 88 | \\ \hline 89 | 90 | \multirow{2}{2cm}{Números primos de Mersenne} 91 | & 3, 7, 31, 127, 8191, 131071, 524287, 2147483647, ... 92 | \\ \cline{2-2} 93 | & $f(n) = 2^{p(n)} - 1$ donde $p$ representa valores primos iniciando en $p(0)=2$. 94 | \\ \hline 95 | 96 | 97 | \multirow{2}{2cm}{Números tetraedrales} 98 | & 1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 286, 364, 455, ... 99 | \\ \cline{2-2} 100 | & $f(n) = \displaystyle\frac{n*(n+1)*(n+2)}{6}$ 101 | 102 | \\ \hline 103 | 104 | 105 | \multirow{2}{2cm}{Números triangulares} 106 | & 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, ... 107 | \\ \cline{2-2} 108 | & $f(n) = \displaystyle\frac{n(n+1)}{2}$ 109 | 110 | \\ \hline 111 | 112 | 113 | \multirow{2}{2cm}{OEIS A000127} 114 | & 1, 2, 4, 8, 16, 31, 57, 99, 163, 256, 386, 562, ... 115 | \\ \cline{2-2} 116 | & $f(n) = \displaystyle\frac{(n^{4}-6n^{3}+23n^{2}-18{n}+24)}{24}$. 117 | 118 | \\ \hline 119 | 120 | 121 | \multirow{2}{2cm}{Secuencia de Narayana} 122 | & 1, 1, 1, 2, 3, 4, 6, 9, 13, 19, 28, 41, 60, 88, 129, ... 123 | \\ \cline{2-2} 124 | & $f(0) = f(1) = f(2) = 1; f(n) = f(n-1) + f(n-3)$ para todo $n>2$. 125 | \\ \hline 126 | 127 | 128 | \multirow{2}{2cm} 129 | {Secuencia de Silvestre} 130 | & 2, 3, 7, 43, 1807, 3263443, 10650056950807, ... 131 | \\ \cline{2-2} 132 | & $f(0) = 2; f(n+1) = f(n)^2 - f(n) + 1$ 133 | \\ \hline 134 | 135 | \multirow{2}{2cm}{Secuencia de vendedor perezoso} 136 | & 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, 56, 67, 79, 92, 106, ... 137 | \\ \cline{2-2} 138 | & Equivale al triangular(n) + 1. Máxima número de piezas que se pueden formar al hacer n cortes a un disco. 139 | 140 | $f(n) = \displaystyle\frac{n(n+1)}{2} + 1$ 141 | 142 | \\ \hline 143 | 144 | \multirow{2}{2cm}{Suma de los divisores de un número} 145 | & 1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, ... 146 | \\ \cline{2-2} 147 | &Para todo $n>1$ cuya descomposición en factores primos es $n=\displaystyle p_{1}^{\textstyle a_{1}}\displaystyle p_{2}^{\textstyle a_{2}}...\displaystyle p_{k}^{\textstyle a_{k}}$ se tiene que: 148 | 149 | 150 | $f(n) = \displaystyle\frac{p_{1}^{a_{1} + 1} - 1}{p_{1} - 1} * \frac{p_{2}^{a_{2} + 1} - 1}{p_{2} - 1} * ... * \frac{p_{k}^{a_{k} + 1} - 1}{p_{k} - 1}$ 151 | 152 | \\ \hline 153 | \end{supertabular} 154 | } 155 | \end{center} 156 | -------------------------------------------------------------------------------- /java [outdated]/Values sequences and results/Time Complexities.tex: -------------------------------------------------------------------------------- 1 | 2 | Aproximación del mayor número n de datos que pueden procesarse para cada una de las complejidades algoritmicas. Tomar esta tabla solo como referencia. 3 | 4 | \begin{tabbing} 5 | \textbf{Complexity}\hspace{4cm} \= \textbf{n}\hspace{3cm} \\ 6 | $O(n!)$ \> 11\\ 7 | $O(n^{5})$ \> 50\\ 8 | $O(2^{n}*n^{2})$ \> 18\\ 9 | $O(2^{n}*n)$ \> 22\\ 10 | $O(n^{4})$ \> 100\\ 11 | $O(n^{3})$ \> 500\\ 12 | $O(n^{2}\log_{2}n)$ \> 1.000\\ 13 | $O(n^{2})$ \> 10.000\\ 14 | $O(n\log_{2}n)$ \> $10^{6}$\\ 15 | $O(n)$ \> $10^{8}$\\ 16 | $O(\sqrt{n})$ \> $10^{16}$\\ 17 | $O(\log_{2}n)$ \> -\\ 18 | $O(1)$ \> -\\ 19 | \end{tabbing} 20 | -------------------------------------------------------------------------------- /logonotebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgramacionCompetitivaUFPS/notebook/0e08e9435c333c575848408b46738d1f89cdc38f/logonotebook.png --------------------------------------------------------------------------------