├── doc ├── strategy.pdf ├── modmul-proof.pdf ├── scripts │ ├── README │ ├── skip_headers │ ├── test-compiles.sh │ ├── format-all.sh │ ├── validate-formatting.sh │ ├── add-cc0-license.py │ ├── find-unreferenced-files.py │ ├── fix-newlines.py │ ├── run-all.sh │ ├── compile-all.sh │ └── inline_includes.py └── example.h ├── content ├── tex │ ├── kth.pdf │ └── TheTab_KGcmyk.pdf ├── contest │ ├── chapter.tex │ ├── hash.sh │ └── template.cpp ├── geometry │ ├── ConvexHull.pdf │ ├── PolygonCut.pdf │ ├── circumcircle.pdf │ ├── lineDistance.pdf │ ├── SegmentDistance.pdf │ ├── lineIntersection.pdf │ ├── SegmentIntersection.pdf │ ├── linearTransformation.pdf │ ├── PolyhedronVolume.h │ ├── OnSegment.h │ ├── PolygonCenter.h │ ├── PolygonArea.h │ ├── CircleLine.h │ ├── LineProjectionReflection.h │ ├── HullDiameter.h │ ├── CircleIntersection.h │ ├── SegmentDistance.h │ ├── MinimumEnclosingCircle.h │ ├── ClosestPair.h │ ├── linearTransformation.h │ ├── sideOf.h │ ├── angleCmp.h │ ├── lineDistance.h │ ├── circumcircle.h │ ├── DelaunayTriangulation.h │ ├── PointInsideHull.h │ ├── PolygonCut.h │ ├── InsidePolygon.h │ ├── sphericalDistance.h │ ├── ConvexHull.h │ ├── HullTangents.h │ ├── CirclePolygonIntersection.h │ ├── CircleTangents.h │ ├── mitlineIntersection.h │ ├── lineIntersection.h │ ├── ManhattanMST.h │ ├── chapter.tex │ ├── SegmentIntersection.h │ ├── Point.h │ ├── 3dHull.h │ └── PolygonUnion.h ├── math │ ├── sphericalCoordinates.pdf │ ├── Fraction.h │ ├── FracBinarySearch.h │ ├── ContinuedFractions.h │ └── FractionOverflow.h ├── number-theory │ ├── FloorRange.h │ ├── ModPow.h │ ├── ModInverse.h │ ├── ExtendedEuclidean.h │ ├── CRT.h │ ├── PrimeSieve.h │ ├── chapter.tex │ ├── CountPrimes.h │ ├── MillerRabin.h │ ├── MultiplicativeSieve.h │ ├── MultiplicativePrefixSum.h │ ├── phiFunction.h │ ├── ModSqrt.h │ ├── ModMulLL.h │ ├── BerlekampMassey.h │ ├── LinearRecurrence.h │ ├── PrimeSieveFast.h │ ├── mobius.tex │ └── ModInt.h ├── solutions │ └── chapter.tex ├── test-session │ ├── test-session.tex │ └── chapter.tex ├── strings │ ├── ZValues.h │ ├── chapter.tex │ ├── MinRotation.h │ ├── KMP.h │ ├── FMIndex.h │ ├── Manacher.h │ ├── ahocorasick.h │ ├── SuffixArray.h │ └── Hashing.h ├── misc │ ├── LowerHigher.h │ ├── StackTrick.java │ ├── OverflowMult.h │ ├── SubmasksSupermasks.h │ ├── chapter.tex │ ├── HilbertMos.h │ ├── NDimensionalVector.h │ ├── stackhack.cpp │ ├── LIS.h │ ├── FastMod.h │ ├── IntervalContainer.h │ └── Mos.java ├── crackpack │ ├── EulerTour.java │ ├── DisjointSet.java │ ├── zValues.java │ ├── Gaussian.java │ ├── BIT.java │ ├── FastScanner.java │ ├── chapter.tex │ ├── SteinerTrees.java │ ├── PolygonClipping.java │ ├── VecL.java │ ├── LCA.java │ ├── Vec.java │ ├── JS.java │ ├── Plane.java │ ├── TwoSat.java │ ├── ConvexHull.java │ ├── Mos.java │ └── SegTree.java ├── combinatorial │ ├── factorialMod.h │ ├── IntPerm.h │ ├── multinomial.h │ ├── binomialModPrime.h │ ├── factorial.tex │ └── schreier-sims.cpp ├── data-structures │ ├── DSU.h │ ├── chapter.tex │ ├── RMQ.h │ ├── HashMap.h │ ├── SubMatrix.h │ ├── OrderStatisticTree.h │ ├── DSURestorable.h │ ├── BIT.h │ ├── IterativeSegmentTree.h │ ├── Matrix.h │ ├── SegTreeWalk.h │ ├── KDBIT.h │ ├── MonotonicQueue.h │ ├── LinkCutTree.h │ ├── LineContainer.h │ ├── LiChaoTree.h │ └── LazyIterativeSegTree.h ├── numerical │ ├── SolveLinear2.h │ ├── TernarySearch.java │ ├── HillClimbing.h │ ├── Integrate.h │ ├── Determinant.h │ ├── chapter.tex │ ├── IntDeterminant.h │ ├── SumOverSubsets.h │ ├── IntegrateAdaptive.h │ ├── FastSubsetTransform.h │ ├── GoldenSectionSearch.h │ ├── SolveLinear.h │ ├── Multipoint.h │ ├── MatrixInverse.h │ ├── FastFourierTransformMod.h │ └── MatrixInverse-mod.h ├── graphs │ ├── LCA.h │ ├── Dijkstra.h │ ├── GlobalMinCut.h │ ├── SCCKosaraju.h │ ├── MaximalCliques.h │ ├── chapter.tex │ ├── CompressTree.h │ ├── EulerWalk.h │ ├── TreeLifting.h │ ├── GomoryHu.h │ ├── SCCTarjan.h │ ├── TwoEdgeCCs.h │ ├── TwoVertexCCs.h │ ├── GeneralMatching.h │ ├── DominatorTree.h │ ├── Blossom.h │ ├── WeightedMatching.h │ ├── KactlDinic.h │ └── EdgeColoring.h └── kactl.tex ├── .gitignore ├── tests ├── data-structures │ ├── DSU.test.cpp │ ├── RMQ.test.cpp │ ├── BITKth.test.cpp │ ├── BIT.test.cpp │ ├── RMQLambda.test.cpp │ ├── BIT_cf.cpp │ ├── KDBIT.cpp │ ├── DSURestorable.test.cpp │ ├── LiChaoTree.test.cpp │ ├── MonotonicQueue.cpp │ └── DSURestorable.cpp ├── graphs │ ├── LCA.test.cpp │ ├── TreeLiftingLCA.test.cpp │ ├── DominatorTree.test.cpp │ ├── Blossom.test.cpp │ ├── LCA.cpp │ ├── TreeLiftingKth.test.cpp │ ├── Dijkstra_kth_popup.cpp │ ├── TwoVertexCCs.test.cpp │ ├── Dijkstra_NAQC.cpp │ ├── SCCKosaraju.cpp │ └── SCCTarjan.cpp ├── TestRunner.h ├── numerical │ └── SumOverSubsets.cpp ├── strings │ └── ZValues.cpp ├── math │ ├── PrimeSieve.cpp │ └── PrimeSieveFast.cpp └── number-theory │ └── MultiplicativePrefix.test.cpp ├── example.h ├── .verify-helper └── timestamps.remote.json └── format.sh /doc/strategy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/doc/strategy.pdf -------------------------------------------------------------------------------- /content/tex/kth.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/tex/kth.pdf -------------------------------------------------------------------------------- /doc/modmul-proof.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/doc/modmul-proof.pdf -------------------------------------------------------------------------------- /doc/scripts/README: -------------------------------------------------------------------------------- 1 | Just a bunch of miscellaneous scripts I don't want to throw away. You may safely ignore them. 2 | -------------------------------------------------------------------------------- /content/tex/TheTab_KGcmyk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/tex/TheTab_KGcmyk.pdf -------------------------------------------------------------------------------- /content/contest/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Contest} 2 | 3 | \kactlimport[-l rawcpp]{template.cpp} 4 | \kactlimport[-l raw]{hash.sh} 5 | -------------------------------------------------------------------------------- /content/geometry/ConvexHull.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/geometry/ConvexHull.pdf -------------------------------------------------------------------------------- /content/geometry/PolygonCut.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/geometry/PolygonCut.pdf -------------------------------------------------------------------------------- /content/geometry/circumcircle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/geometry/circumcircle.pdf -------------------------------------------------------------------------------- /content/geometry/lineDistance.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/geometry/lineDistance.pdf -------------------------------------------------------------------------------- /content/geometry/SegmentDistance.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/geometry/SegmentDistance.pdf -------------------------------------------------------------------------------- /content/geometry/lineIntersection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/geometry/lineIntersection.pdf -------------------------------------------------------------------------------- /content/math/sphericalCoordinates.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/math/sphericalCoordinates.pdf -------------------------------------------------------------------------------- /content/geometry/SegmentIntersection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/geometry/SegmentIntersection.pdf -------------------------------------------------------------------------------- /content/geometry/linearTransformation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ucf-programming-team/hackpack-cpp/HEAD/content/geometry/linearTransformation.pdf -------------------------------------------------------------------------------- /content/number-theory/FloorRange.h: -------------------------------------------------------------------------------- 1 | for (int i = 1, la; i <= n; i = la + 1) { 2 | la = n / (n / i); 3 | //n / x yields the same value for i <= x <= la. 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !*/ 3 | !*.* 4 | /build/ 5 | a.out 6 | header.tmp 7 | .vscode 8 | *.pyc 9 | /snippets/ 10 | kactl.pdf 11 | test-session.pdf 12 | *.gch 13 | -------------------------------------------------------------------------------- /doc/scripts/skip_headers: -------------------------------------------------------------------------------- 1 | SolveLinear2.h 2 | Unrolling.h 3 | MinCostMaxFlow.h 4 | DivideAndConquerDP.h 5 | ModInverse.h 6 | ModSqrt.h 7 | Hashing-codeforces.h 8 | NumberTheoreticTransform.h 9 | -------------------------------------------------------------------------------- /content/contest/hash.sh: -------------------------------------------------------------------------------- 1 | # Hashes a file, ignoring all whitespace and comments. Use for 2 | # verifying that code was correctly typed. 3 | cpp -dD -P -fpreprocessed | tr -d '[:space:]'| md5sum |cut -c-6 4 | -------------------------------------------------------------------------------- /doc/scripts/test-compiles.sh: -------------------------------------------------------------------------------- 1 | mkdir -p build 2 | FILE="$1" 3 | echo " 4 | #include \"../content/contest/template.cpp\" 5 | #include \"../$FILE\" 6 | " >build/temp.cpp 7 | g++ -Wall -Wextra -Wfatal-errors -Wconversion -std=c++14 build/temp.cpp && rm a.out build/temp.cpp -------------------------------------------------------------------------------- /content/solutions/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Solutions} 2 | 3 | \kactlimport{CaptainAmerica.h} 4 | \kactlimport{PointRotator.h} 5 | \kactlimport{RadixSum.h} 6 | \kactlimport{DynamicDiameter.h} 7 | \kactlimport{TotientSum.h} 8 | 9 | % extra stuff found 10 | \kactlimport{EditDistance.java} 11 | -------------------------------------------------------------------------------- /content/test-session/test-session.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt, a4paper, notitlepage]{report} 2 | \usepackage{kactlpkg} 3 | \kactlcontentdir{content} 4 | 5 | \university{KTH}{}{} 6 | 7 | \begin{document} 8 | \begin{multicols*}{3} 9 | \kactlchapter{test-session} 10 | \end{multicols*} 11 | \end{document} 12 | -------------------------------------------------------------------------------- /doc/scripts/format-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Compiling formatter..." 4 | raco exe -o run-formatter ++lib format /Users/seba/cp/format/format/run-direct.rkt 5 | 6 | find $1 -type f | grep -E ".*\.(cpp|h)$" | 7 | xargs -I '{}' zsh format.sh {} 8 | 9 | # echo "Formatted:" 10 | # find $1 -type f | grep -E ".*\.(cpp|h)$" 11 | -------------------------------------------------------------------------------- /content/strings/ZValues.h: -------------------------------------------------------------------------------- 1 | vector zValues(string& s) { 2 | int n = (int)s.length(); 3 | vector z(n); 4 | for (int i = 1, L = 0, R = 0; i < n; ++i) { 5 | if (i <= R) z[i] = min(R - i + 1, z[i - L]); 6 | while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; 7 | if (i + z[i] - 1 > R) L = i, R = i + z[i] - 1; } 8 | return z; } 9 | -------------------------------------------------------------------------------- /content/misc/LowerHigher.h: -------------------------------------------------------------------------------- 1 | template 2 | auto lower(const S& s, const T& x, bool strict = 0) { 3 | auto it = strict ? s.lower_bound(x) : s.upper_bound(x); 4 | return it == begin(s) ? end(s) : prev(it); } 5 | template 6 | auto higher(const S& s, const T& x, bool strict = 0) { 7 | return strict ? s.upper_bound(x) : s.lower_bound(x); } 8 | -------------------------------------------------------------------------------- /doc/scripts/validate-formatting.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | find . -type f | 3 | grep -E ".*\.(cpp|h)$" | 4 | xargs -n1 clang-format-15 -style=file -output-replacements-xml | 5 | grep "/dev/null 6 | if [ $? -ne 1 ]; then 7 | echo "Commit did not match clang-format-15" 8 | echo "Please run 'make format' and recommit" 9 | exit 1 10 | fi 11 | -------------------------------------------------------------------------------- /content/contest/template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | usingnamespace std; 3 | #define rep(i, a, b) for (int i = a; i < (b); ++i) 4 | #define all(x) begin(x), end(x) 5 | #define sz(x) (int)(x).size() 6 | using ll = long long; 7 | using pii = pair; 8 | using vi = vector; 9 | int main() { 10 | cin.tie(0)->sync_with_stdio(0); 11 | cin.exceptions(cin.failbit); } 12 | -------------------------------------------------------------------------------- /content/misc/StackTrick.java: -------------------------------------------------------------------------------- 1 | public class StackTrick implements Runnable { 2 | public static void main(String[] args) { 3 | // adjust the size as needed 4 | new Thread(null, new StackTrick(), "", (1 << 24)).start(); 5 | } 6 | public void run() { 7 | solve(); 8 | } 9 | void solve() { 10 | // solve the problem here 11 | System.out.println("brother."); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /content/misc/OverflowMult.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Daniel West 3 | * License: CC0 4 | * Description: returns min(MAX, a * b) without overflowing 2*MAX. Assumes a,b <= MAX 5 | * Time: $O(1)$ 6 | * Status: NOT TESTED 7 | */ 8 | #pragma once 9 | const ll MAX = 2e18; 10 | ll mult(ll a, ll b) { 11 | if (b == 0) return 0; 12 | if (a >= (MAX + b - 1) / b) return MAX; 13 | return a * b; } 14 | -------------------------------------------------------------------------------- /content/number-theory/ModPow.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Noam527 3 | * Date: 2019-04-24 4 | * License: CC0 5 | * Source: folklore 6 | * Description: 7 | * Status: tested 8 | */ 9 | #pragma once 10 | const ll mod = 1000000007; // faster if const 11 | ll modpow(ll b, ll e) { 12 | ll ans = 1; 13 | for (; e; b = b * b % mod, e /= 2) if (e & 1) 14 | ans = ans * b % mod; 15 | return ans; } 16 | -------------------------------------------------------------------------------- /content/crackpack/EulerTour.java: -------------------------------------------------------------------------------- 1 | class Edge { 2 | boolean dead = false; int to; Edge rev; 3 | public Edge(int t) { to = t; } 4 | } 5 | Deque[] adj; // use ArrayDeque for ease 6 | Deque tour; 7 | void eulerCircuit(int u) { 8 | while(!adj[u].isEmpty()) { 9 | Edge e = adj[u].pop(); 10 | if(e.dead) continue; 11 | e.rev.dead = true; 12 | eulerCircuit(e.to); 13 | } 14 | tour.addFirst(u); 15 | } -------------------------------------------------------------------------------- /tests/data-structures/DSU.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/unionfind" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/data-structures/DSU.h" 4 | 5 | void test() { 6 | int n, q; 7 | cin >> n >> q; 8 | 9 | DSU dsu(n); 10 | 11 | while (q--) { 12 | int t, x, y; 13 | cin >> t >> x >> y; 14 | 15 | if (t == 0) dsu.join(x, y); 16 | else 17 | cout << dsu.same(x, y) << "\n"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/data-structures/RMQ.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/data-structures/RMQ.h" 4 | 5 | void test() { 6 | int n, q; 7 | cin >> n >> q; 8 | 9 | vector a(n); 10 | for (auto& x : a) cin >> x; 11 | RMQ rmq(a); 12 | 13 | while (q--) { 14 | int x, y; 15 | cin >> x >> y; 16 | cout << rmq.query(x, y) << "\n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /content/combinatorial/factorialMod.h: -------------------------------------------------------------------------------- 1 | int factmod(int n, int p) { 2 | vector f(p); 3 | f[0] = 1; 4 | for (int i = 1; i < p; i++) f[i] = f[i - 1] * i % p; 5 | int res = 1; 6 | while (n > 1) { 7 | if ((n / p) % 2) res = p - res; 8 | res = res * f[n % p] % p; 9 | n /= p; } 10 | return res; } 11 | int multiplicityFactorial(int n, int p) { 12 | int count = 0; 13 | do { n /= p; count += n; } while (n); 14 | return count; } 15 | -------------------------------------------------------------------------------- /content/geometry/PolyhedronVolume.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Mattias de Zalenski 3 | * Date: 2002-11-04 4 | * Description: Magic formula for the volume of a polyhedron. Faces should point outwards. 5 | * Status: tested 6 | */ 7 | #pragma once 8 | template 9 | double signedPolyVolume(const V& p, const L& trilist) { 10 | double v = 0; 11 | for (auto i : trilist) 12 | v += p[i.a].cross(p[i.b]).dot(p[i.c]); 13 | return v / 6; } 14 | -------------------------------------------------------------------------------- /content/number-theory/ModInverse.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2016-07-24 4 | * License: CC0 5 | * Source: Russian page 6 | * Description: Pre-computation of modular inverses. Assumes LIM $\le$ mod and that mod is a prime. 7 | * Status: Works 8 | */ 9 | #pragma once 10 | // const ll mod = 1000000007, LIM = 200000; ///include-line 11 | ll* inv = new ll[LIM] - 1; 12 | inv[1] = 1; 13 | rep(i, 2, LIM) inv[i] = mod - (mod / i) * inv[mod % i] % mod; 14 | -------------------------------------------------------------------------------- /content/strings/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Strings} 2 | 3 | \kactlimport{KMP.h} 4 | \kactlimport{ahocorasick.h} 5 | % \kactlimport{KactlAhoCorasick.h} 6 | 7 | \kactlimport{MinRotation.h} 8 | \kactlimport{SuffixArray.h} 9 | \kactlimport{FMIndex.h} 10 | \kactlimport{KactlSuffixTree.h} 11 | % \kactlimport{SuffixTree.h} 12 | \kactlimport{eertree.h} 13 | % \kactlimport{Eertree.java} 14 | 15 | \kactlimport{ZValues.h} 16 | \kactlimport{Manacher.h} 17 | \kactlimport{Hashing.h} 18 | -------------------------------------------------------------------------------- /content/crackpack/DisjointSet.java: -------------------------------------------------------------------------------- 1 | static class DisjointSet { 2 | int[] s; 3 | 4 | public DisjointSet(int n) { 5 | Arrays.fill(s = new int[n], -1); 6 | } 7 | 8 | public int find(int i) { 9 | return s[i] < 0 ? i : (s[i] = find(s[i])); 10 | } 11 | 12 | public boolean union(int a, int b) { 13 | if ((a = find(a)) == (b = find(b))) return false; 14 | if(s[a] == s[b]) s[a]--; 15 | if(s[a] <= s[b]) s[b] = a; else s[a] = b; 16 | return true; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /content/misc/SubmasksSupermasks.h: -------------------------------------------------------------------------------- 1 | /** Description: Iterate over all masks and 2 | * their submasks in O(3^n). 3 | */ 4 | void submasks(int n) { 5 | for (int mask = 0; mask < (1 << n); mask++) 6 | for (int sub = mask; sub; sub = (sub - 1) & mask) { 7 | // do thing 8 | } 9 | } 10 | void supermasks(int n) { 11 | for (int mask = 0; mask < (1 << n); mask++) 12 | for (int sup = mask; sup < (1 << n); 13 | sup = (sup + 1) | mask) { 14 | // do thing 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /content/misc/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Miscellaneous} 2 | 3 | \kactlimport{LowerHigher.h} 4 | \kactlimport{HilbertMos.h} 5 | % \kactlimport{NDimensionalVector.h} 6 | \kactlimport{SubmasksSupermasks.h} 7 | % \kactlimport{Mos.java} 8 | % \kactlimport{StackTrick.java} 9 | \kactlimport{FastMod.h} 10 | \kactlimport{IntervalContainer.h} 11 | \kactlimport{LIS.h} 12 | \kactlimport{MoQueries.h} 13 | \kactlimport{OverflowMult.h} 14 | % \kactlimport{SIMD.h} 15 | % \kactlimport{stackhack.cpp} 16 | -------------------------------------------------------------------------------- /content/combinatorial/IntPerm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2018-07-06 4 | * License: CC0 5 | * Description: Permutation -> integer conversion. (Not order preserving.) 6 | * Integer -> permutation can use a lookup table. 7 | * Time: O(n) 8 | */ 9 | #pragma once 10 | int permToInt(vi& v) { 11 | int use = 0, i = 0, r = 0; 12 | for (int x : v) 13 | r = r * ++i + __builtin_popcount(use & -(1 << x)), 14 | use |= 1 << x; // (note: minus, not ~!) 15 | return r; } 16 | -------------------------------------------------------------------------------- /doc/scripts/add-cc0-license.py: -------------------------------------------------------------------------------- 1 | 2 | for fname in open('todo'): 3 | fname = fname.strip() 4 | print(fname) 5 | with open(fname) as f: 6 | cont = list(f) 7 | beforeline = -1 8 | for i, line in enumerate(cont): 9 | if line.startswith(' * Author:') or line.startswith(' * Date:'): 10 | beforeline = i+1 11 | cont[beforeline:beforeline] = [' * License: CC0\n'] 12 | cont = ''.join(cont) 13 | with open(fname, 'w') as f: 14 | f.write(cont) 15 | -------------------------------------------------------------------------------- /content/geometry/OnSegment.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Victor Lecomte, chilli 3 | * Date: 2019-04-26 4 | * License: CC0 5 | * Source: https://vlecomte.github.io/cp-geo.pdf 6 | * Description: Returns true iff p lies on the line segment from s to e. 7 | * Use \texttt{(segDist(s,e,p)<=epsilon)} instead when using Point. 8 | * Status: 9 | */ 10 | #pragma once 11 | #include "Point.h" 12 | template bool onSegment(P s, P e, P p) { 13 | return p.cross(s, e) == 0 && (s - p).dot(e - p) <= 0; } 14 | -------------------------------------------------------------------------------- /doc/scripts/find-unreferenced-files.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | for (dirpath, dirnames, filenames) in os.walk('content'): 4 | try: 5 | with open(os.path.join(dirpath, 'chapter.tex')) as f: 6 | chapter_tex = f.read() 7 | except: 8 | continue 9 | 10 | for fname in filenames: 11 | if not fname.endswith('.h') or '-codeforces' in fname: 12 | continue 13 | if f'{{{fname}}}' in chapter_tex: 14 | continue 15 | print(os.path.join(dirpath, fname)) 16 | -------------------------------------------------------------------------------- /tests/data-structures/BITKth.test.cpp: -------------------------------------------------------------------------------- 1 | #define IGNORE // atcoder tests currently don't work due to dropbox 2 | #define PROBLEM "https://atcoder.jp/contests/abc234/tasks/abc234_d" 3 | #include "../../tests/TestRunner.h" 4 | #include "../../content/data-structures/BIT.h" 5 | 6 | void test() { 7 | int n, k; 8 | cin >> n >> k; 9 | 10 | BIT bit(n); 11 | for (int i = 0; i < n; i++) { 12 | int x; 13 | cin >> x; 14 | bit.update(n - x, 1); 15 | if (i >= k - 1) cout << n - bit.kth(k - 1) << "\n"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /content/combinatorial/multinomial.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Mattias de Zalenski, Fredrik Niemelä, Per Austrin, Simon Lindholm 3 | * Date: 2002-09-26 4 | * Source: Max Bennedich 5 | * Description: Computes $\displaystyle \binom{k_1 + \dots + k_n}{k_1, k_2, \dots, k_n} = \frac{(\sum k_i)!}{k_1!k_2!...k_n!}$. 6 | * Status: Tested on kattis:lexicography 7 | */ 8 | #pragma once 9 | ll multinomial(vi& v) { 10 | ll c = 1, m = v.empty() ? 1 : v[0]; 11 | rep (i, 1, sz(v)) rep (j, 0, v[i]) c = c * ++m / (j + 1); 12 | return c; } 13 | -------------------------------------------------------------------------------- /content/misc/HilbertMos.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Source: https://codeforces.com/blog/entry/61203 3 | * Description: Maps points on a $2^k \times 2^k$ matrix 4 | * to their index on the Hilbert curve. 5 | */ 6 | const int logn = 21, maxn = 1 << logn; 7 | ll hilbert(int x, int y) { 8 | ll d = 0; 9 | for (int s = 1 << (logn - 1); s > 0; s >>= 1) { 10 | int rx = x & s, ry = y & s; 11 | d = d << 2 | rx * 3 ^ ry; 12 | if (ry == 0) { 13 | if (rx != 0) { x = maxn - x; y = maxn - y; } 14 | swap(x, y); } } 15 | return d; } 16 | -------------------------------------------------------------------------------- /content/number-theory/ExtendedEuclidean.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Unknown 3 | * Date: 2002-09-15 4 | * Source: predates tinyKACTL 5 | * Description: Finds two integers $x$ and $y$, such that $ax+by=\gcd(a,b)$. If 6 | * you just need gcd, use the built in \texttt{\_\_gcd} instead. 7 | * If $a$ and $b$ are coprime, then $x$ is the inverse of $a \pmod{b}$. 8 | */ 9 | #pragma once 10 | ll euclid(ll a, ll b, ll& x, ll& y) { 11 | if (!b) return x = 1, y = 0, a; 12 | ll d = euclid(b, a % b, y, x); 13 | return y -= a / b * x, d; } 14 | -------------------------------------------------------------------------------- /tests/graphs/LCA.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/lca" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/graphs/LCA.h" 4 | 5 | void test() { 6 | int n, q; 7 | cin >> n >> q; 8 | 9 | vector adj(n); 10 | for (int i = 1; i < n; i++) { 11 | int p; 12 | cin >> p; 13 | adj[p].push_back(i); 14 | adj[i].push_back(p); 15 | } 16 | 17 | LCA t(adj); 18 | 19 | for (int i = 0; i < q; i++) { 20 | int u, v; 21 | cin >> u >> v; 22 | cout << t.lca(u, v) << "\n"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/TestRunner.h: -------------------------------------------------------------------------------- 1 | // This file is the driver for all of the .test.cpp files in tests/, 2 | // for use with the verifier CI. 3 | #include 4 | using namespace std; 5 | #define sz(x) int(size(x)) 6 | #define rep(a, b, c) for (int a = (b); a < (c); a++) 7 | #define all(x) begin(x), end(x) 8 | using ll = long long; 9 | using vi = vector; 10 | using pii = pair; 11 | 12 | void test(); 13 | 14 | int main() { 15 | cin.tie(0)->sync_with_stdio(0); 16 | cin.exceptions(cin.failbit); 17 | 18 | test(); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /tests/graphs/TreeLiftingLCA.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/lca" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/graphs/TreeLifting.h" 4 | 5 | void test() { 6 | int n, q; 7 | cin >> n >> q; 8 | 9 | vector adj(n); 10 | for (int i = 1; i < n; i++) { 11 | int p; 12 | cin >> p; 13 | adj[p].push_back(i); 14 | adj[i].push_back(p); 15 | } 16 | 17 | lift t(adj); 18 | 19 | for (int i = 0; i < q; i++) { 20 | int u, v; 21 | cin >> u >> v; 22 | cout << t.lca(u, v) << "\n"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/data-structures/BIT.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/point_add_range_sum" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/data-structures/BIT.h" 4 | 5 | void test() { 6 | int n, q; 7 | cin >> n >> q; 8 | 9 | BIT bit(n); 10 | for (int i = 0; i < n; i++) { 11 | int x; 12 | cin >> x; 13 | bit.update(i, x); 14 | } 15 | 16 | while (q--) { 17 | int t, x, y; 18 | cin >> t >> x >> y; 19 | 20 | if (t == 0) bit.update(x, y); 21 | else 22 | cout << bit.query(x, y) << "\n"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /content/geometry/PolygonCenter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-04-08 4 | * License: CC0 5 | * Source: 6 | * Description: Returns the center of mass for a polygon. 7 | * Time: O(n) 8 | * Status: Tested 9 | */ 10 | #pragma once 11 | #include "Point.h" 12 | typedef Point P; 13 | P polygonCenter(const vector

& v) { 14 | P res(0, 0); 15 | double A = 0; 16 | for (int i = 0, j = sz(v) - 1; i < sz(v); j = i++) { 17 | res = res + (v[i] + v[j]) * v[j].cross(v[i]); 18 | A += v[j].cross(v[i]); } 19 | return res / A / 3; } 20 | -------------------------------------------------------------------------------- /content/geometry/PolygonArea.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-03-21 4 | * License: CC0 5 | * Source: tinyKACTL 6 | * Description: Returns twice the signed area of a polygon. 7 | * Clockwise enumeration gives negative area. Watch out for overflow if using int as T! 8 | * Status: Stress-tested and tested on kattis:polygonarea 9 | */ 10 | #pragma once 11 | #include "Point.h" 12 | template T polygonArea2(vector>& v) { 13 | T a = v.back().cross(v[0]); 14 | rep (i, 0, sz(v) - 1) a += v[i].cross(v[i + 1]); 15 | return a; } 16 | -------------------------------------------------------------------------------- /content/data-structures/DSU.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Maintains union of disjoint sets. 3 | * Time: $O(\alpha(n))$ amortized 4 | */ 5 | struct DSU { 6 | vector s; 7 | DSU(int n): s(n, -1) {} 8 | int find(int i) { return s[i] < 0 ? i : s[i] = find(s[i]); } 9 | bool join(int a, int b) { 10 | a = find(a), b = find(b); 11 | if (a == b) return false; 12 | if (s[a] > s[b]) swap(a, b); 13 | s[a] += s[b], s[b] = a; 14 | return true; } 15 | int size(int i) { return -s[find(i)]; } 16 | bool same(int a, int b) { return find(a) == find(b); } }; 17 | -------------------------------------------------------------------------------- /tests/numerical/SumOverSubsets.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/subset_convolution" 2 | #include "../../tests/TestRunner.h" 3 | 4 | const int MOD = 998244353; 5 | 6 | #include "../../content/number-theory/ModInt.h" 7 | #include "../../content/numerical/SumOverSubsets.h" 8 | 9 | void test() { 10 | int n; 11 | cin >> n; 12 | 13 | vector a(1 << n), b(1 << n); 14 | 15 | for (auto& x : a) cin >> x.v; 16 | for (auto& x : b) cin >> x.v; 17 | 18 | auto c = conv(a, b); 19 | 20 | for (auto& x : c) cout << int(x) << " "; 21 | cout << "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /content/misc/NDimensionalVector.h: -------------------------------------------------------------------------------- 1 | /** 2 | * if you provide less than D args for dimension, it is assumed 3 | * to be 0 examples: Vec<2, int> a(10, 50); // int a[10][50] 4 | * initialized with zero Vec<3, double> b(n, m, k, 3.14); // 5 | * double b[n][m][k] initialized with 3.14 6 | */ 7 | template struct Vec: vector> { 8 | template 9 | Vec(int n = 0, Args... args): 10 | vector>(n, Vec(args...)) {} 11 | }; 12 | template struct Vec<1, T>: vector { 13 | Vec(int n = 0, const T& val = T()): vector(n, val) {} 14 | }; 15 | -------------------------------------------------------------------------------- /tests/strings/ZValues.cpp: -------------------------------------------------------------------------------- 1 | // tested on https://www.spoj.com/problems/SUFEQPRE/ 2 | #include 3 | using namespace std; 4 | 5 | using ll = long long; 6 | 7 | #include "../../content/strings/ZValues.h" 8 | 9 | int main() { 10 | cin.tie(0)->sync_with_stdio(0); 11 | cin.exceptions(cin.failbit); 12 | 13 | int t; 14 | cin >> t; 15 | for (int tt = 1; tt <= t; tt++) { 16 | string s; 17 | cin >> s; 18 | auto z = zValues(s); 19 | int ans = 0; 20 | for (int i = 1; i < s.length(); i++) ans += (s.length() - i == z[i]); 21 | cout << "Case " << tt << ": " << ans << '\n'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /content/numerical/SolveLinear2.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2016-09-06 4 | * License: CC0 5 | * Source: me 6 | * Description: To get all uniquely determined values of $x$ back from SolveLinear, make the following changes: 7 | * Status: tested on kattis:equationsolverplus, stress-tested 8 | */ 9 | #pragma once 10 | #include "SolveLinear.h" 11 | rep(j, 0, n) if (j != i) // instead of rep(j,i+1,n) 12 | // ... then at the end: 13 | x.assign(m, undefined); 14 | rep(i, 0, rank) { 15 | rep(j, rank, m) if (fabs(A[i][j]) > eps) goto fail; 16 | x[col[i]] = b[i] / A[i][i]; 17 | fail:; 18 | } 19 | -------------------------------------------------------------------------------- /tests/data-structures/RMQLambda.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/staticrmq" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/data-structures/RMQ.h" 4 | 5 | void test() { 6 | int n, q; 7 | cin >> n >> q; 8 | 9 | vector a(n); 10 | for (auto& x : a) cin >> x; 11 | // test lambda comparison 12 | auto cmp = [&](int x, int y) { return a[x] < a[y]; }; 13 | vector idx(n); 14 | iota(idx.begin(), idx.end(), 0); 15 | RMQ rmq(idx, cmp); 16 | 17 | while (q--) { 18 | int x, y; 19 | cin >> x >> y; 20 | cout << a[rmq.query(x, y)] << "\n"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /content/misc/stackhack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | stackhack.cpp 3 | Use this shit when sparta is being annoying 4 | */ 5 | #include // important 6 | int main(void) { 7 | const rlim_t kStackSize = 1024 * 1024 * 1024; 8 | struct rlimit rl; 9 | int result; 10 | result = getrlimit(RLIMIT_STACK, &rl); 11 | if (result == 0) { 12 | // std::cerr << rl.rlim_cur << std::endl; 13 | if (rl.rlim_cur < kStackSize) { 14 | rl.rlim_cur = kStackSize; 15 | result = setrlimit(RLIMIT_STACK, &rl); 16 | // if (result != 0) 17 | // std::cerr << "setrlimit returned result = " << result << "\n"; 18 | } 19 | } 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /tests/math/PrimeSieve.cpp: -------------------------------------------------------------------------------- 1 | // tested on https://open.kattis.com/problems/primesieve 2 | #include 3 | using namespace std; 4 | 5 | using ll = long long; 6 | 7 | #include "../../content/number-theory/PrimeSieve.h" 8 | // change MAX_PR to 9 | // const int MAX_PR = 100'000'000; 10 | 11 | int main() { 12 | cin.tie(0)->sync_with_stdio(0); 13 | cin.exceptions(cin.failbit); 14 | 15 | int n, q; 16 | cin >> n >> q; 17 | 18 | vector primes = primeSieve(n + 1); 19 | cout << primes.size() << '\n'; 20 | 21 | for (int i = 0; i < q; i++) { 22 | int x; 23 | cin >> x; 24 | cout << isprime[x] << '\n'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/graphs/DominatorTree.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/dominatortree" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/graphs/DominatorTree.h" 4 | 5 | void test() { 6 | int n, m, s; 7 | cin >> n >> m >> s; 8 | 9 | vector adj(n); 10 | for (int i = 0; i < m; i++) { 11 | int a, b; 12 | cin >> a >> b; 13 | adj[a].push_back(b); 14 | } 15 | 16 | auto tree = dominator_tree(adj, s); 17 | 18 | vi p(n, -1); 19 | p[s] = s; 20 | for (int i = 0; i < n; i++) 21 | for (int j : tree[i]) p[j] = i; 22 | 23 | for (int i = 0; i < n; i++) cout << p[i] << ' '; 24 | cout << '\n'; 25 | } 26 | -------------------------------------------------------------------------------- /content/numerical/TernarySearch.java: -------------------------------------------------------------------------------- 1 | class TernarySearch { 2 | public static void main (String[] args){ 3 | double l = -(1e9 + 3), r = 1e9 + 3; 4 | for(int i = 0; i < 200; ++i){ 5 | double g1 = (l * 2 + r) / 3; 6 | double g2 = (l + r * 2) / 3; 7 | //if finding min 8 | if(go(g1) > go(g2)) l = g1; 9 | else r = g2; 10 | //if finding max 11 | if(go(g1) > go(g2)) r = g2; 12 | else l = g1; 13 | } 14 | double out = go(l); 15 | } 16 | static double go(double in){ 17 | //function you're min/max ing 18 | return -Math.pow(in - 4, 2) + 3; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/graphs/Blossom.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/general_matching" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/graphs/Blossom.h" 4 | 5 | void test() { 6 | int n, m; 7 | cin >> n >> m; 8 | 9 | vector adj(n); 10 | for (int i = 0; i < m; i++) { 11 | int u, v; 12 | cin >> u >> v; 13 | adj[u].push_back(v); 14 | adj[v].push_back(u); 15 | } 16 | 17 | auto mate = Blossom(adj); 18 | int ans = 0; 19 | for (int i = 0; i < n; i++) ans += mate[i] > i; 20 | 21 | cout << ans << "\n"; 22 | for (int i = 0; i < n; i++) 23 | if (mate[i] > i) cout << i << " " << mate[i] << "\n"; 24 | } 25 | -------------------------------------------------------------------------------- /tests/math/PrimeSieveFast.cpp: -------------------------------------------------------------------------------- 1 | // tested on https://open.kattis.com/problems/primesieve 2 | #include 3 | using namespace std; 4 | 5 | using ll = long long; 6 | 7 | #include "../../content/number-theory/PrimeSieveFast.h" 8 | 9 | int main() { 10 | cin.tie(0)->sync_with_stdio(0); 11 | cin.exceptions(cin.failbit); 12 | 13 | int n, q; 14 | cin >> n >> q; 15 | 16 | vector allPrimes = primeSieve(); 17 | int cnt = 0; 18 | for (int i : allPrimes) 19 | if (i <= n) cnt++; 20 | 21 | cout << cnt << '\n'; 22 | 23 | for (int i = 0; i < q; i++) { 24 | int x; 25 | cin >> x; 26 | cout << isPrime[x] << '\n'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /content/numerical/HillClimbing.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2015-02-04 4 | * License: CC0 5 | * Source: Johan Sannemo 6 | * Description: Poor man's optimization for unimodal functions. 7 | * Status: used with great success 8 | */ 9 | #pragma once 10 | typedef array P; 11 | template pair hillClimb(P start, F f) { 12 | pair cur(f(start), start); 13 | for (double jmp = 1e9; jmp > 1e-20; jmp /= 2) { 14 | rep (j, 0, 100) rep (dx, -1, 2) rep (dy, -1, 2) { 15 | P p = cur.second; 16 | p[0] += dx * jmp; 17 | p[1] += dy * jmp; 18 | cur = min(cur, make_pair(f(p), p)); } } 19 | return cur; } 20 | -------------------------------------------------------------------------------- /content/strings/MinRotation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Stjepan Glavina 3 | * License: Unlicense 4 | * Source: https://github.com/stjepang/snippets/blob/master/min_rotation.cpp 5 | * Description: Finds the lexicographically smallest rotation of a string. 6 | * Time: O(N) 7 | * Usage: 8 | * rotate(v.begin(), v.begin()+minRotation(v), v.end()); 9 | * Status: Stress-tested 10 | */ 11 | #pragma once 12 | int minRotation(string s) { 13 | int a = 0, N = sz(s); 14 | s += s; 15 | rep (b, 0, N) rep (k, 0, N) { 16 | if (a + k == b || s[a + k] < s[b + k]) { 17 | b += max(0, k - 1); 18 | break; } 19 | if (s[a + k] > s[b + k]) { a = b; break; } } 20 | return a; } 21 | -------------------------------------------------------------------------------- /content/numerical/Integrate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2015-02-11 4 | * License: CC0 5 | * Source: Wikipedia 6 | * Description: Simple integration of a function over an interval using 7 | * Simpson's rule. The error should be proportional to $h^4$, although in 8 | * practice you will want to verify that the result is stable to desired 9 | * precision when epsilon changes. 10 | * Status: mostly untested 11 | */ 12 | #pragma once 13 | template 14 | double quad(double a, double b, F f, const int n = 1000) { 15 | double h = (b - a) / 2 / n, v = f(a) + f(b); 16 | rep (i, 1, n * 2) v += f(a + i * h) * (i & 1 ? 4 : 2); 17 | return v * h / 3; } 18 | -------------------------------------------------------------------------------- /example.h: -------------------------------------------------------------------------------- 1 | /** 2 | * YOU HAVE TO USE BLOCK COMMENTS FOR THE HEADER 3 | * 4 | * the list of tags: 5 | * ['Author', 'Date', 'Description', 'Source', 'Time', 6 | * 'Memory', 'License', 'Status', 'Usage', 'Details'] not all 7 | * of these are needed 8 | * 9 | * Author: Author of the code 10 | * Source: Source of the code/pseudocode used 11 | * Description: A short description that goes in the hackpack, 12 | * describing the code 13 | * Usage: foo(ptr) 14 | * Time: $O(1)$. Time complexity of the code. This also goes in 15 | * the hackpack Time: $O(1)$. Memory complexity of the code. 16 | * This also goes in the hackpack Status: Untested 17 | */ 18 | void foo(int* ptr) { cout << ptr << '\n'; } -------------------------------------------------------------------------------- /content/number-theory/CRT.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2019-05-22 4 | * License: CC0 5 | * Description: Chinese Remainder Theorem. 6 | * 7 | * \texttt{crt(a, m, b, n)} computes $x$ such that $x\equiv a \pmod m$, $x\equiv b \pmod n$. 8 | * If $|a| < m$ and $|b| < n$, $x$ will obey $0 \le x < \text{lcm}(m, n)$. 9 | * Assumes $mn < 2^{62}$. 10 | * Time: $\log(n)$ 11 | * Status: Works 12 | */ 13 | #pragma once 14 | #include "ExtendedEuclidean.h" 15 | ll crt(ll a, ll m, ll b, ll n) { 16 | if (n > m) swap(a, b), swap(m, n); 17 | ll x, y, g = euclid(m, n, x, y); 18 | assert((a - b) % g == 0); // else no solution 19 | x = (b - a) % n * x % n / g * m + a; 20 | return x < 0 ? x + m * n / g : x; } 21 | -------------------------------------------------------------------------------- /content/number-theory/PrimeSieve.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Prime sieve for generating all primes up 3 | * to a certain limit. isprime$[i]$ is true iff $i$ is a prime. 4 | * Time: lim=100'000'000 $\approx$ 0.8 s. Runs 30\% faster if 5 | * only odd indices are stored. 6 | */ 7 | const int MAX_PR = 5'000'000; 8 | bitset isprime; 9 | vector primeSieve(int lim) { 10 | isprime.set(); 11 | isprime[0] = isprime[1] = 0; 12 | for (int i = 4; i < lim; i += 2) isprime[i] = 0; 13 | for (int i = 3; i * i < lim; i += 2) if (isprime[i]) 14 | for (int j = i * i; j < lim; j += i * 2) isprime[j] = 0; 15 | vector pr; 16 | for (int i = 2; i < lim; i++) if (isprime[i]) 17 | pr.push_back(i); 18 | return pr; } 19 | -------------------------------------------------------------------------------- /doc/scripts/fix-newlines.py: -------------------------------------------------------------------------------- 1 | import glob 2 | 3 | for fname in glob.glob('content/*/*.h'): 4 | fname = fname.strip() 5 | with open(fname) as f: 6 | cont = list(f) 7 | prline = -1 8 | for i, line in enumerate(cont): 9 | if line.startswith('#pragma once'): 10 | prline = i 11 | if prline == -1: 12 | continue 13 | print(fname) 14 | while not cont[prline-1].strip(): 15 | del cont[prline-1] 16 | prline -= 1 17 | while not cont[prline+1].strip(): 18 | del cont[prline+1] 19 | cont[prline+1:prline+1] = ['\n'] 20 | cont = ''.join(cont) 21 | # print(cont) 22 | # print() 23 | with open(fname, 'w') as f: 24 | f.write(cont) 25 | -------------------------------------------------------------------------------- /tests/data-structures/BIT_cf.cpp: -------------------------------------------------------------------------------- 1 | // tested on https://codeforces.com/contest/1354/problem/D 2 | #include 3 | using namespace std; 4 | 5 | using ll = long long; 6 | 7 | #include "../../content/data-structures/BIT.h" 8 | 9 | int main() { 10 | cin.tie(0)->sync_with_stdio(0); 11 | cin.exceptions(cin.failbit); 12 | 13 | int n, q; 14 | cin >> n >> q; 15 | 16 | BIT bit(n + 1); 17 | 18 | for (int i = 0; i < n; i++) { 19 | int x; 20 | cin >> x; 21 | bit.update(x, 1); 22 | } 23 | 24 | while (q--) { 25 | int i; 26 | cin >> i; 27 | 28 | if (i > 0) bit.update(i, 1); 29 | else 30 | bit.update(bit.kth(-i - 1), -1); 31 | } 32 | 33 | cout << (bit.query(n + 1) ? bit.kth(0) : 0) << '\n'; 34 | } 35 | -------------------------------------------------------------------------------- /content/data-structures/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Data structures} 2 | 3 | \kactlimport{DSU.h} 4 | \kactlimport{DSURestorable.h} 5 | \kactlimport{BIT.h} 6 | % \kactlimport{KDBIT.h} 7 | \kactlimport{RMQ.h} 8 | \kactlimport{HashMap.h} 9 | \kactlimport{OrderStatisticTree.h} 10 | \kactlimport{IterativeSegmentTree.h} 11 | \kactlimport{LazyIterativeSegTree.h} 12 | \kactlimport{SegTreeWalk.h} 13 | \kactlimport{YoinkedWavelet.h} 14 | \kactlimport{LineContainer.h} 15 | \kactlimport{LiChaoTree.h} 16 | \kactlimport{MonotonicQueue.h} 17 | \kactlimport{SplayTree.h} 18 | % \kactlimport{Splay.h} 19 | \kactlimport{LinkCutTree.h} 20 | \kactlimport{Treaps.h} 21 | % \kactlimport{implicittreap.cpp} 22 | % \kactlimport{Matrix.h} 23 | % \kactlimport{SubMatrix.h} 24 | -------------------------------------------------------------------------------- /content/geometry/CircleLine.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Victor Lecomte, chilli 3 | * Date: 2019-10-29 4 | * License: CC0 5 | * Source: https://vlecomte.github.io/cp-geo.pdf 6 | * Description: Finds the intersection between a circle and a line. 7 | * Returns a vector of either 0, 1, or 2 intersection points. 8 | * P is intended to be Point. 9 | * Status: unit tested 10 | */ 11 | #pragma once 12 | #include "Point.h" 13 | template 14 | vector

circleLine(P c, double r, P a, P b) { 15 | P ab = b - a, p = a + ab*(c - a).dot(ab) / ab.dist2(); 16 | double s = a.cross(b, c), h2 = r * r - s * s / ab.dist2(); 17 | if (h2 < 0) return {}; 18 | if (h2 == 0) return {p}; 19 | P h = ab.unit() * sqrt(h2); 20 | return {p - h, p + h}; } 21 | -------------------------------------------------------------------------------- /content/data-structures/RMQ.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Constant time subarray min/max queries for a 3 | * fixed array. Queries are inclusive-exclusive. 4 | * Time: $O(n log n)$ initialization and $O(1)$ queries. 5 | * Status: Tested 6 | */ 7 | template> struct RMQ { 8 | vector> t; 9 | C cmp; 10 | RMQ(vector& a, C cmp = C{}): 11 | t(__lg(sz(a)) + 1, a), cmp(cmp) { 12 | for (int k = 1, len = 1; k < sz(t); k++, len <<= 1) 13 | for (int i = 0; i + 2 * len - 1 < sz(a); i++) 14 | t[k][i] = min(t[k - 1][i], t[k - 1][i + len], cmp); } 15 | T query(int a, int b) { // inclusive-exclusive [a, b) 16 | int k = __lg(b - a), len = 1 << k; 17 | return min(t[k][a], t[k][b - len], cmp); } }; 18 | -------------------------------------------------------------------------------- /content/number-theory/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Number Theory} 2 | 3 | \import{mobius.tex} 4 | \kactlimport{FloorRange.h} 5 | \kactlimport{MultiplicativeSieve.h} 6 | \kactlimport{MultiplicativePrefixSum.h} 7 | \kactlimport{phiFunction.h} 8 | 9 | \kactlimport{MillerRabin.h} 10 | % \kactlimport{PrimeSieve.h} 11 | \kactlimport{PrimeSieveFast.h} 12 | \kactlimport{Factor.h} 13 | \kactlimport{CountPrimes.h} 14 | 15 | \kactlimport{ExtendedEuclidean.h} 16 | \kactlimport{CRT.h} 17 | % CF Ax + By = N trick 18 | 19 | \kactlimport{ModInverse.h} 20 | \kactlimport{ModMulLL.h} 21 | \kactlimport{ModPow.h} 22 | \kactlimport{ModLog.h} 23 | \kactlimport{ModSqrt.h} 24 | % \kactlimport{ModInt.h} 25 | 26 | \kactlimport{BerlekampMassey.h} 27 | % \kactlimport{LinearRecurrence.h} 28 | -------------------------------------------------------------------------------- /content/numerical/Determinant.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2016-09-06 4 | * License: CC0 5 | * Source: folklore 6 | * Description: Calculates determinant of a matrix. Destroys the matrix. 7 | * Time: $O(N^3)$ 8 | * Status: somewhat tested 9 | */ 10 | #pragma once 11 | double det(vector>& a) { 12 | int n = sz(a); 13 | double res = 1; 14 | rep (i, 0, n) { 15 | int b = i; 16 | rep (j, i + 1, n) if (fabs(a[j][i]) > fabs(a[b][i])) 17 | b = j; 18 | if (i != b) swap(a[i], a[b]), res *= -1; 19 | res *= a[i][i]; 20 | if (res == 0) return 0; 21 | rep (j, i + 1, n) { 22 | double v = a[j][i] / a[i][i]; 23 | if (v != 0) rep (k, i + 1, n) a[j][k] -= v * a[i][k]; } 24 | } 25 | return res; } 26 | -------------------------------------------------------------------------------- /content/geometry/LineProjectionReflection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Victor Lecomte, chilli 3 | * Date: 2019-10-29 4 | * License: CC0 5 | * Source: https://vlecomte.github.io/cp-geo.pdf 6 | * Description: Projects point p onto line ab. Set refl=true to get reflection 7 | * of point p across line ab insted. The wrong point will be returned if P is 8 | * an integer point and the desired point doesn't have integer coordinates. 9 | * Products of three coordinates are used in intermediate steps so watch out 10 | * for overflow. 11 | * Status: stress-tested 12 | */ 13 | #pragma once 14 | #include "Point.h" 15 | template 16 | P lineProj(P a, P b, P p, bool refl = false) { 17 | P v = b - a; 18 | return p - v.perp() * (1 + refl) * v.cross(p - a) / v.dist2(); 19 | } 20 | -------------------------------------------------------------------------------- /tests/graphs/LCA.cpp: -------------------------------------------------------------------------------- 1 | // tested on Library-Checker: Lowest Common Ancestor 2 | // https://judge.yosupo.jp/problem/lca 3 | #include 4 | #define all(x) begin(x), end(x) 5 | using namespace std; 6 | 7 | using ll = long long; 8 | 9 | #include "../../content/graphs/LCA.h" 10 | 11 | int main() { 12 | cin.tie(0)->sync_with_stdio(0); 13 | cin.exceptions(cin.failbit); 14 | 15 | int n, q; 16 | cin >> n >> q; 17 | 18 | vector> adj(n); 19 | 20 | for (int i = 1; i < n; i++) { 21 | int p; 22 | cin >> p; 23 | adj[p].push_back(i); 24 | adj[i].push_back(p); // check undirected case 25 | } 26 | 27 | LCA lca(adj); 28 | 29 | for (int i = 0; i < q; i++) { 30 | int u, v; 31 | cin >> u >> v; 32 | cout << lca.lca(u, v) << '\n'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /content/numerical/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Numerical} 2 | 3 | \kactlimport{FastFourierTransform.h} 4 | \kactlimport{NumberTheoreticTransform.h} 5 | \kactlimport{FastFourierTransformMod.h} 6 | \kactlimport{FastSubsetTransform.h} 7 | \kactlimport{SumOverSubsets.h} 8 | \kactlimport{Multipoint.h} 9 | % \kactlimport{mitfft.h} 10 | \kactlimport{polynomial.cpp} 11 | 12 | \kactlimport{Simplex.h} 13 | \kactlimport{Integrate.h} 14 | \kactlimport{IntegrateAdaptive.h} 15 | % \kactlimport{HillClimbing.h} 16 | % \kactlimport{GoldenSectionSearch.h} 17 | % \kactlimport{TernarySearch.java} 18 | 19 | \kactlimport{SolveLinear.h} 20 | \kactlimport{SolveLinear2.h} 21 | \kactlimport{Determinant.h} 22 | \kactlimport{IntDeterminant.h} 23 | \kactlimport{MatrixInverse.h} 24 | \kactlimport{MatrixInverse-mod.h} 25 | -------------------------------------------------------------------------------- /content/crackpack/zValues.java: -------------------------------------------------------------------------------- 1 | // z[i] is equal to the length of the longest substring starting //% 2 | // at i that is also a prefix of the overall string. //% 3 | // O(n) //% 4 | public int[] zValues(String string) { 5 | int n = string.length(); char[] s = string.toCharArray(); 6 | int[] z = new int[n]; z[0] = n; 7 | int L = 0, R = 0; 8 | int[] left = new int[n], right = new int[n]; 9 | for(int i = 1; i < n; ++i) { 10 | if(i > R) { 11 | L = R = i; 12 | while(R < n && s[R-L] == s[R]) R++; 13 | z[i] = R - L; R--; 14 | } else { 15 | int k = i-L; 16 | if(z[k] < R-i+1) z[i] = z[k]; 17 | else { 18 | L = i; 19 | while(R < n && s[R-L] == s[R]) R++; 20 | z[i] = R - L; R--; 21 | } 22 | } 23 | left[i] = L; right[i] = R; 24 | } 25 | return z; 26 | } 27 | -------------------------------------------------------------------------------- /content/strings/KMP.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Johan Sannemo 3 | * Date: 2016-12-15 4 | * License: CC0 5 | * Description: pi[x] computes the length of the longest prefix of s that ends at x, other than s[0...x] itself (abacaba -> 0010123). 6 | * Can be used to find all occurrences of a string. 7 | * Time: O(n) 8 | * Status: Tested on kattis:stringmatching 9 | */ 10 | #pragma once 11 | vi pi(const string& s) { 12 | vi p(sz(s)); 13 | rep (i, 1, sz(s)) { 14 | int g = p[i - 1]; 15 | while (g && s[i] != s[g]) g = p[g - 1]; 16 | p[i] = g + (s[i] == s[g]); } 17 | return p; } 18 | vi match(const string& s, const string& pat) { 19 | vi p = pi(pat + '\0' + s), res; 20 | rep (i, sz(p) - sz(s), sz(p)) if (p[i] == sz(pat)) 21 | res.push_back(i - 2 * sz(pat)); 22 | return res; } 23 | -------------------------------------------------------------------------------- /content/crackpack/Gaussian.java: -------------------------------------------------------------------------------- 1 | // R * C * min(R,C) 2 | public static void gaussian(double[][] m, boolean augmented) { 3 | int R = m.length, C = m[0].length; 4 | int pc = 0, pr = 0; 5 | while(pr < r && pc < (augmented ? C-1 : C )) { 6 | int sr = pr; 7 | for (int j = pr + 1; j < R; j++) 8 | if (Math.abs(m[j][pc]) > Math.abs(m[sr][pc])) 9 | sr = j; 10 | swap(m, sr, pr); 11 | if (eq(m[pr][pc],0)) { // indpt variable 12 | pc++; 13 | continue; 14 | } 15 | double piv = m[pr][pc]; 16 | for (int j = pc; j < C; j++) 17 | m[pr][j] /= piv; 18 | for (int j = 0; j < R; j++) { 19 | if(j == pr) continue; 20 | double ratio = -m[j][pc]; 21 | for (int k = pc; k < C; k++) { 22 | m[j][k] += m[pr][k] * ratio; 23 | } 24 | } 25 | pc++; 26 | pr++; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /content/crackpack/BIT.java: -------------------------------------------------------------------------------- 1 | static class BIT { 2 | int n, tree[]; 3 | public BIT(int N) { 4 | n = N; tree = new int[N + 1]; 5 | } 6 | void update(int i, int val) { 7 | for (i++; i <= n; i += i & -i) tree[i] += val; 8 | } 9 | int read(int i) { 10 | int sum = 0; 11 | for (i++; i > 0; i -= i & -i) sum += tree[i]; 12 | return sum; 13 | } 14 | // query sum of [l, r] inclusive 15 | int query(int l, int r) { return read(r) - read(l - 1); } 16 | // if the BIT is a freq array, returns the index of the 17 | // kth item (0-indexed), or n if there are <= k items. 18 | int getKth(int k) { 19 | if (k < 0) return -1; 20 | int i = 0; 21 | for (int pw = Integer.highestOneBit(n); pw > 0; pw >>= 1) 22 | if (i + pw <= n && tree[i + pw] <= k) k -= tree[i += pw]; 23 | return i; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /content/geometry/HullDiameter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Oleksandr Bacherikov, chilli 3 | * Date: 2019-05-05 4 | * License: Boost Software License 5 | * Source: https://codeforces.com/blog/entry/48868 6 | * Description: Returns the two points with max distance on a convex hull (ccw, 7 | * no duplicate/collinear points). 8 | * Status: stress-tested, tested on kattis:roberthood 9 | */ 10 | #pragma once 11 | #include "Point.h" 12 | typedef Point P; 13 | array hullDiameter(vector

S) { 14 | int n = sz(S), j = n < 2 ? 0 : 1; 15 | pair> res({0, {S[0], S[0]}}); 16 | rep (i, 0, j) for (; ; j = (j + 1) % n) { 17 | res = max(res, {(S[i] - S[j]).dist2(), {S[i], S[j]}}); 18 | if ((S[(j + 1) % n] - S[j]).cross(S[i + 1] - S[i]) >= 0) 19 | break; } 20 | return res.second; } 21 | -------------------------------------------------------------------------------- /content/strings/FMIndex.h: -------------------------------------------------------------------------------- 1 | const int LIM = 26, A = 'A'; 2 | struct FMIndex : SuffixArray { 3 | vector> freq; 4 | array occ = {1}; 5 | FMIndex(string& s): SuffixArray(s), freq(sz(s) + 2) { 6 | rep (i, 0, sz(sa)) { 7 | freq[i + 1] = freq[i]; 8 | int p = sa[i] - 1; 9 | if (p >= 0) 10 | freq[i + 1][s[p] - A]++, occ[s[p] - A + 1]++; } 11 | rep (i, 0, LIM) occ[i + 1] += occ[i]; } 12 | // prepend c at pos i 13 | int add(int i, char c) { 14 | return occ[c - A] + freq[i][c - A]; } 15 | vector query(string& q) { // inclusive-exclusive 16 | vector ret(sz(q) + 1); 17 | auto [L, R] = ret.back() = {0, sz(sa)}; 18 | for (int i = sz(q) - 1; i >= 0; i--) 19 | ret[i] = {L = add(L, q[i]), R = add(R, q[i])}; 20 | return ret; } }; 21 | -------------------------------------------------------------------------------- /content/graphs/LCA.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Answers lowest common ancestor 3 | * queries on a rooted tree using RMQ. Works with 4 | * both directed and undirected adjacency lists. 5 | * Time: $O(1)$ queries with an $O(n \log{n})$ precomp (RMQ). 6 | */ 7 | #include "../../content/data-structures/RMQ.h" 8 | struct LCA { 9 | int T = 0; 10 | vector pre, inv, tour; 11 | RMQ rmq; 12 | LCA(vector& adj, int root = 0): 13 | pre(sz(adj)), inv(pre), rmq((dfs(adj, root), tour)) {} 14 | void dfs(vector& adj, int u, int p = -1) { 15 | inv[pre[u] = T++] = u; 16 | for (int v : adj[u]) if (v != p) 17 | tour.push_back(pre[u]), dfs(adj, v, u); } 18 | int lca(int u, int v) { 19 | if (u == v) return u; 20 | tie(u, v) = minmax(pre[u], pre[v]); 21 | return inv[rmq.query(u, v)]; } }; 22 | -------------------------------------------------------------------------------- /content/data-structures/HashMap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm, chilli 3 | * Date: 2018-07-23 4 | * License: CC0 5 | * Source: http://codeforces.com/blog/entry/60737 6 | * Description: Hash map with mostly the same API as unordered\_map, but \tilde 7 | * 3x faster. Uses 1.5x memory. 8 | * Initial capacity must be a power of 2 (if provided). 9 | */ 10 | #include /** keep-include */ 11 | // To use most bits rather than just the lowest ones: 12 | struct chash { // large odd number for C 13 | const uint64_t C = ll(4e18 * acos(0)) | 71; 14 | ll operator()(ll x) const { 15 | return __builtin_bswap64(x * C); 16 | } 17 | }; 18 | __gnu_pbds::gp_hash_table h({}, {}, {}, {}, 19 | {1 << 16}); 20 | template // for auto resize 21 | using hash_map = __gnu_pbds::gp_hash_table; 22 | -------------------------------------------------------------------------------- /content/data-structures/SubMatrix.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Johan Sannemo 3 | * Date: 2014-11-28 4 | * License: CC0 5 | * Source: Folklore 6 | * Description: Calculate submatrix sums quickly, given upper-left and lower-right corners (half-open). 7 | * Usage: 8 | * SubMatrix m(matrix); 9 | * m.sum(0, 0, 2, 2); // top left 4 elements 10 | * Time: O(N^2 + Q) 11 | * Status: Tested on Kattis 12 | */ 13 | #pragma once 14 | template struct SubMatrix { 15 | vector> p; 16 | SubMatrix(vector>& v) { 17 | int R = sz(v), C = sz(v[0]); 18 | p.assign(R + 1, vector(C + 1)); 19 | rep (r, 0, R) rep (c, 0, C) 20 | p[r + 1][c + 1] = v[r][c] + p[r][c + 1] + p[r + 1][c] - p[r][c]; 21 | } 22 | T sum(int u, int l, int d, int r) { 23 | return p[d][r] - p[d][l] - p[u][r] + p[u][l]; } }; 24 | -------------------------------------------------------------------------------- /content/geometry/CircleIntersection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2015-09-01 4 | * License: CC0 5 | * Description: Computes the pair of points at which two circles intersect. Returns false in case of no intersection. 6 | * Status: stress-tested 7 | */ 8 | #pragma once 9 | #include "Point.h" 10 | typedef Point P; 11 | bool circleInter(P a, P b, double r1, double r2, 12 | pair* out) { 13 | if (a == b) return assert(r1 != r2), false; 14 | P vec = b - a; 15 | double d2 = vec.dist2(), sum = r1 + r2, dif = r1 - r2, 16 | p = (d2 + r1 * r1 - r2 * r2) / (d2 * 2), 17 | h2 = r1 * r1 - p * p * d2; 18 | if (sum * sum < d2 || dif * dif > d2) return false; 19 | P mid = a + vec * p, 20 | per = vec.perp() * sqrt(fmax(0, h2) / d2); 21 | *out = {mid + per, mid - per}; 22 | return true; 23 | } 24 | -------------------------------------------------------------------------------- /tests/graphs/TreeLiftingKth.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/jump_on_tree" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/graphs/TreeLifting.h" 4 | 5 | void test() { 6 | int n, q; 7 | cin >> n >> q; 8 | 9 | vector adj(n); 10 | for (int i = 0; i < n - 1; i++) { 11 | int u, v; 12 | cin >> u >> v; 13 | adj[u].push_back(v); 14 | adj[v].push_back(u); 15 | } 16 | 17 | lift t(adj); 18 | 19 | for (int i = 0; i < q; i++) { 20 | int u, v, k; 21 | cin >> u >> v >> k; 22 | int lca = t.lca(u, v); 23 | if (k < t.d[u] - t.d[lca] + 1) cout << t.kth(u, k) << "\n"; 24 | else { 25 | k -= t.d[u] - t.d[lca] + 1; 26 | k = t.d[v] - t.d[lca] - 1 - k; 27 | 28 | if (k >= 0) cout << t.kth(v, k) << "\n"; 29 | else 30 | cout << -1 << "\n"; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /content/numerical/IntDeterminant.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Unknown 3 | * Date: 2014-11-27 4 | * Source: somewhere on github 5 | * Description: Calculates determinant using modular arithmetics. 6 | * Modulos can also be removed to get a pure-integer version. 7 | * Time: $O(N^3)$ 8 | * Status: bruteforce-tested for N <= 3, mod <= 7 9 | */ 10 | #pragma once 11 | const ll mod = 12345; 12 | ll det(vector>& a) { 13 | int n = sz(a); 14 | ll ans = 1; 15 | rep (i, 0, n) { 16 | rep (j, i + 1, n) { 17 | while (a[j][i] != 0) { // gcd step 18 | ll t = a[i][i] / a[j][i]; 19 | if (t) rep (k, i, n) 20 | a[i][k] = (a[i][k] - a[j][k] * t) % mod; 21 | swap(a[i], a[j]); 22 | ans *= -1; } } 23 | ans = ans * a[i][i] % mod; 24 | if (!ans) return 0; } 25 | return (ans + mod) % mod; } 26 | -------------------------------------------------------------------------------- /content/geometry/SegmentDistance.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-03-21 4 | * License: CC0 5 | * Source: 6 | * Description:\\ 7 | \begin{minipage}{75mm} 8 | Returns the shortest distance between point p and the line segment from point s to e. 9 | \end{minipage} 10 | \begin{minipage}{15mm} 11 | \vspace{-10mm} 12 | \includegraphics[width=\textwidth]{content/geometry/SegmentDistance} 13 | \end{minipage} 14 | * Usage: 15 | * Point a, b(2,2), p(1,1); 16 | * bool onSegment = segDist(a,b,p) < 1e-10; 17 | * Status: tested 18 | */ 19 | #pragma once 20 | #include "Point.h" 21 | typedef Point P; 22 | double segDist(P& s, P& e, P& p) { 23 | if (s == e) return (p - s).dist(); 24 | auto d = (e - s).dist2(), 25 | t = min(d, max(.0, (p - s).dot(e - s))); 26 | return ((p - s) * d - (e - s) * t).dist() / d; } 27 | -------------------------------------------------------------------------------- /content/graphs/Dijkstra.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Computes shortest paths from s 3 | * to any node reachable from s. 4 | * Pass in an adjacency list of pairs (node, weight). 5 | * Time: $O((|V| + |E|) \log{|V|})$ 6 | */ 7 | template 8 | pair, vector> 9 | dijkstra(const vector>>& adj, int s) { 10 | using ST = pair; /// state type 11 | priority_queue, greater> q; 12 | vector dist(adj.size()); 13 | vector seen(adj.size()); 14 | q.emplace(T{}, s); 15 | seen[s] = 1; 16 | while (!q.empty()) { 17 | auto [d, u] = q.top(); 18 | q.pop(); 19 | if (dist[u] < d) continue; 20 | for (auto [v, w] : adj[u]) 21 | if (!seen[v] || d + w < dist[v]) { 22 | q.emplace(dist[v] = d + w, v); 23 | seen[v] = 1; } } 24 | return {seen, dist}; } 25 | -------------------------------------------------------------------------------- /content/combinatorial/binomialModPrime.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Håkan Terelius 3 | * Date: 2009-09-25 4 | * License: CC0 5 | * Source: http://en.wikipedia.org/wiki/Lucas'_theorem 6 | * Description: Lucas' thm: Let $n,m$ be non-negative integers and $p$ a prime. 7 | * Write $n=n_kp^k+...+n_1p+n_0$ and $m=m_kp^k+...+m_1p+m_0$. 8 | * Then $\binom{n}{m} \equiv \prod_{i=0}^k\binom{n_i}{m_i} \pmod{p}$. 9 | * fact and invfact must hold pre-computed factorials / inverse factorials, e.g. from ModInverse.h. 10 | * Status: Untested 11 | * Time: O(\log_p n) 12 | */ 13 | #pragma once 14 | ll chooseModP(ll n, ll m, int p, vi& fact, vi& invfact) { 15 | ll c = 1; 16 | while (n || m) { 17 | ll a = n % p, b = m % p; 18 | if (a < b) return 0; 19 | c = c * fact[a] % p * invfact[b] % p * invfact[a - b] % p; 20 | n /= p, m /= p; } 21 | return c; } 22 | -------------------------------------------------------------------------------- /content/geometry/MinimumEnclosingCircle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Andrew He, chilli 3 | * Date: 2019-05-07 4 | * License: CC0 5 | * Source: folklore 6 | * Description: Computes the minimum circle that encloses a set of points. 7 | * Time: expected O(n) 8 | * Status: stress-tested 9 | */ 10 | #pragma once 11 | #include "circumcircle.h" 12 | pair mec(vector

ps) { 13 | shuffle(all(ps), mt19937(time(0))); 14 | P o = ps[0]; 15 | double r = 0, EPS = 1 + 1e-8; 16 | rep (i, 0, sz(ps)) if ((o - ps[i]).dist() > r * EPS) { 17 | o = ps[i], r = 0; 18 | rep (j, 0, i) if ((o - ps[j]).dist() > r * EPS) { 19 | o = (ps[i] + ps[j]) / 2; 20 | r = (o - ps[i]).dist(); 21 | rep (k, 0, j) if ((o - ps[k]).dist() > r * EPS) { 22 | o = ccCenter(ps[i], ps[j], ps[k]); 23 | r = (o - ps[i]).dist(); } } } 24 | return {o, r}; } 25 | -------------------------------------------------------------------------------- /content/misc/LIS.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Johan Sannemo 3 | * License: CC0 4 | * Description: Compute indices for the longest increasing subsequence. 5 | * Time: $O(N \log N)$ 6 | * Status: Tested on kattis:longincsubseq, stress-tested 7 | */ 8 | #pragma once 9 | template vi lis(const vector& S) { 10 | if (S.empty()) return {}; 11 | vi prev(sz(S)); 12 | typedef pair p; 13 | vector

res; 14 | rep (i, 0, sz(S)) { 15 | // change 0 -> i for longest non-decreasing subsequence 16 | auto it = lower_bound(all(res), p{S[i], 0}); 17 | if (it == res.end()) 18 | res.emplace_back(), it = res.end() - 1; 19 | *it = {S[i], i}; 20 | prev[i] = it == res.begin() ? 0 : (it - 1)->second; } 21 | int L = sz(res), cur = res.back().second; 22 | vi ans(L); 23 | while (L--) ans[L] = cur, cur = prev[cur]; 24 | return ans; } 25 | -------------------------------------------------------------------------------- /content/strings/Manacher.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: User adamant on CodeForces 3 | * Source: http://codeforces.com/blog/entry/12143 4 | * Description: For each position in a string, computes p[0][i] = half length of 5 | * longest even palindrome around pos i (center between i-1 and i), 6 | * p[1][i] = longest odd (half rounded down) (center at i). 7 | * Time: O(N) 8 | * Status: Stress-tested 9 | */ 10 | #pragma once 11 | array manacher(const string& s) { 12 | int n = sz(s); 13 | array p = {vi(n + 1), vi(n)}; 14 | rep (z, 0, 2) for (int i = 0, l = 0, r = 0; i < n; i++) { 15 | int t = r - i + !z; 16 | if (i < r) p[z][i] = min(t, p[z][l + t]); 17 | int L = i - p[z][i], R = i + p[z][i] - !z; 18 | while (L >= 1 && R + 1 < n && s[L - 1] == s[R + 1]) 19 | p[z][i]++, L--, R++; 20 | if (R > r) l = L, r = R; } 21 | return p; } 22 | -------------------------------------------------------------------------------- /content/geometry/ClosestPair.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2019-04-17 4 | * License: CC0 5 | * Source: https://codeforces.com/blog/entry/58747 6 | * Description: Finds the closest pair of points. 7 | * Time: O(n \log n) 8 | * Status: stress-tested 9 | */ 10 | #pragma once 11 | #include "Point.h" 12 | typedef Point P; 13 | pair closest(vector

v) { 14 | assert(sz(v) > 1); 15 | set

S; 16 | sort(all(v), [](P a, P b) { return a.y < b.y; }); 17 | pair> ret{LLONG_MAX, {P(), P()}}; 18 | int j = 0; 19 | for (P p : v) { 20 | P d{1 + (ll)sqrt(ret.first), 0}; 21 | while (v[j].y <= p.y - d.x) S.erase(v[j++]); 22 | auto lo = S.lower_bound(p - d), hi = S.upper_bound(p + d); 23 | for (; lo != hi; ++lo) 24 | ret = min(ret, {(*lo - p).dist2(), {*lo, p}}); 25 | S.insert(p); } 26 | return ret.second; } 27 | -------------------------------------------------------------------------------- /content/geometry/linearTransformation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Per Austrin, Ulf Lundstrom 3 | * Date: 2009-04-09 4 | * License: CC0 5 | * Source: 6 | * Description:\\ 7 | \begin{minipage}{75mm} 8 | Apply the linear transformation (translation, rotation and scaling) which takes line p0-p1 to line q0-q1 to point r. 9 | \end{minipage} 10 | \begin{minipage}{15mm} 11 | \vspace{-8mm} 12 | \includegraphics[width=\textwidth]{content/geometry/linearTransformation} 13 | \vspace{-2mm} 14 | \end{minipage} 15 | * Status: not tested 16 | */ 17 | #pragma once 18 | #include "Point.h" 19 | typedef Point P; 20 | P linearTransformation(const P& p0, const P& p1, const P& q0, 21 | const P& q1, const P& r) { 22 | P dp = p1 - p0, dq = q1 - q0, num(dp.cross(dq), dp.dot(dq)); 23 | return q0 + P((r - p0).cross(num), 24 | (r - p0).dot(num)) / dp.dist2(); } 25 | -------------------------------------------------------------------------------- /content/combinatorial/factorial.tex: -------------------------------------------------------------------------------- 1 | \begin{center} 2 | \begin{tabular}{l} 3 | \begin{tabular}{c|c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c} 4 | $n$ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ 5 | \hline 6 | $n!$ & 1 & 2 & 6 & 24 & 120 & 720 & 5040 & 40320 & 362880 & 3628800\\ 7 | \end{tabular}\\ 8 | \begin{tabular}{c|c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c} 9 | $n$ & 11 & 12 & 13 & 14 & 15 & 16 & 17\\ 10 | \hline 11 | $n!$ & 4.0e7 & 4.8e8 & 6.2e9 & 8.7e10 & 1.3e12 & 2.1e13 & 3.6e14\\ 12 | \end{tabular}\\ 13 | \begin{tabular}{c|c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c} 14 | $n$ & 20 & 25 & 30 & 40 & 50 & 100 & 150 & 171\\ 15 | \hline 16 | $n!$ & 2e18 & 2e25 & 3e32 & 8e47 & 3e64 & 9e157 & 6e262 & \scriptsize{$>$DBL\_MAX}\\ 17 | \end{tabular} 18 | \end{tabular} 19 | \end{center} 20 | -------------------------------------------------------------------------------- /content/geometry/sideOf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-03-21 4 | * License: CC0 5 | * Source: 6 | * Description: Returns where $p$ is as seen from $s$ towards $e$. 1/0/-1 $\Leftrightarrow$ left/on line/right. If the optional argument $eps$ is given 0 is returned if $p$ is within distance $eps$ from the line. P is supposed to be Point where T is e.g. double or long long. It uses products in intermediate steps so watch out for overflow if using int or long long. 7 | * Usage: 8 | * bool left = sideOf(p1,p2,q)==1; 9 | * Status: tested 10 | */ 11 | #pragma once 12 | #include "Point.h" 13 | template 14 | int sideOf(P s, P e, P p) { return sgn(s.cross(e, p)); } 15 | template 16 | int sideOf(const P& s, const P& e, const P& p, double eps) { 17 | auto a = (e - s).cross(p - s); 18 | double l = (e - s).dist() * eps; 19 | return (a > l) - (a < -l); } 20 | -------------------------------------------------------------------------------- /content/crackpack/FastScanner.java: -------------------------------------------------------------------------------- 1 | //@ 2 | static class FastScanner { 3 | BufferedReader br; 4 | StringTokenizer st; 5 | 6 | public FastScanner(InputStream i) { 7 | br = new BufferedReader(new InputStreamReader(i)); 8 | st = new StringTokenizer(""); 9 | } 10 | 11 | public String next() throws IOException { 12 | if(st.hasMoreTokens()) 13 | return st.nextToken(); 14 | else 15 | st = new StringTokenizer(br.readLine()); 16 | return next(); 17 | } 18 | 19 | public int nextInt() throws IOException { 20 | return Integer.parseInt(next()); 21 | } 22 | //# 23 | public long nextLong() throws IOException { 24 | return Long.parseLong(next()); 25 | } 26 | public double nextDouble() throws IOException { 27 | return Double.parseDouble(next()); 28 | } 29 | //$ 30 | } 31 | -------------------------------------------------------------------------------- /.verify-helper/timestamps.remote.json: -------------------------------------------------------------------------------- 1 | { 2 | "tests/data-structures/BIT.test.cpp": "2024-04-09 15:56:48 -0400", 3 | "tests/data-structures/DSU.test.cpp": "2024-04-09 14:46:50 -0400", 4 | "tests/data-structures/DSURestorable.test.cpp": "2024-04-09 14:46:50 -0400", 5 | "tests/data-structures/RMQ.test.cpp": "2024-04-09 15:20:55 -0400", 6 | "tests/data-structures/RMQLambda.test.cpp": "2024-04-09 15:20:55 -0400", 7 | "tests/graphs/Blossom.test.cpp": "2024-04-09 14:46:50 -0400", 8 | "tests/graphs/DominatorTree.test.cpp": "2024-04-09 14:46:50 -0400", 9 | "tests/graphs/LCA.test.cpp": "2024-04-09 15:20:55 -0400", 10 | "tests/graphs/TreeLiftingKth.test.cpp": "2024-04-09 14:46:50 -0400", 11 | "tests/graphs/TreeLiftingLCA.test.cpp": "2024-04-09 14:46:50 -0400", 12 | "tests/graphs/TwoVertexCCs.test.cpp": "2024-04-09 14:46:50 -0400", 13 | "tests/number-theory/MultiplicativePrefix.test.cpp": "2022-11-28 15:06:39 -0500" 14 | } -------------------------------------------------------------------------------- /content/misc/FastMod.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2020-05-30 4 | * License: CC0 5 | * Source: https://en.wikipedia.org/wiki/Barrett_reduction 6 | * Description: Compute $a \% b$ about 5 times faster than usual, where $b$ is constant but not known at compile time. 7 | * Returns a value congruent to $a \pmod b$ in the range $[0, 2b)$. 8 | * Status: proven correct, stress-tested 9 | * Measured as having 4 times lower latency, and 8 times higher throughput, see stress-test. 10 | * Details: 11 | * More precisely, it can be proven that the result equals 0 only if $a = 0$, 12 | * and otherwise lies in $[1, (1 + a/2^64) * b)$. 13 | */ 14 | #pragma once 15 | typedef unsigned long long ull; 16 | struct FastMod { 17 | ull b, m; 18 | FastMod(ull b): b(b), m(-1ULL / b) {} 19 | ull reduce(ull a) { // a % b + (0 or b) 20 | return a - (ull)((__uint128_t(m) * a) >> 64) * b; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /content/crackpack/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{crackpack} 2 | 3 | \kactlimport{BIT.java} 4 | \kactlimport{Circle.java} 5 | \kactlimport{ConvexHull.java} 6 | \kactlimport{Dinic.java} 7 | \kactlimport{DisjointSet.java} 8 | \kactlimport{EulerTour.java} 9 | \kactlimport{FastScanner.java} 10 | \kactlimport{Gaussian.java} 11 | \kactlimport{GeneralMatching.java} 12 | \kactlimport{JS.java} 13 | \kactlimport{LCA.java} 14 | \kactlimport{MagicComponents.java} 15 | \kactlimport{MinCostFlow4.java} 16 | \kactlimport{Mos.java} 17 | \kactlimport{Plane.java} 18 | \kactlimport{PolygonClipping.java} 19 | \kactlimport{SCC.java} 20 | \kactlimport{Seg.java} 21 | \kactlimport{SegL.java} 22 | \kactlimport{SegTree.java} 23 | \kactlimport{Simplex.java} 24 | \kactlimport{SteinerTrees.java} 25 | \kactlimport{TreeHashSharon.java} 26 | \kactlimport{TwoSat.java} 27 | \kactlimport{Vec.java} 28 | \kactlimport{VecL.java} 29 | \kactlimport{zValues.java} 30 | -------------------------------------------------------------------------------- /doc/scripts/run-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | DIR=${1:-.} 3 | tests="$(find $DIR/stress-tests -name '*.cpp')" 4 | declare -i pass=0 5 | declare -i fail=0 6 | failTests="" 7 | ulimit -s 524288 # For 2-sat test 8 | for test in $tests; do 9 | echo "$(basename $test): " 10 | start=`date +%s.%N` 11 | g++ -std=c++14 -O2 $test && ./a.out 12 | retCode=$? 13 | if (($retCode != 0)); then 14 | echo "Failed with $retCode" 15 | fail+=1 16 | failTests="$failTests$test\n" 17 | else 18 | pass+=1 19 | fi 20 | end=`date +%s.%N` 21 | runtime=$( echo "$end - $start" | bc -l ) 22 | echo "Took $runtime seconds" 23 | rm -f a.out 24 | echo 25 | done 26 | echo "$pass/$(($pass+$fail)) tests passed" 27 | if (($fail == 0)); then 28 | echo "No tests failed" 29 | exit 0 30 | else 31 | echo -e "These tests failed: \n $failTests" 32 | exit 1 33 | fi 34 | -------------------------------------------------------------------------------- /tests/graphs/Dijkstra_kth_popup.cpp: -------------------------------------------------------------------------------- 1 | // Tested on https://open.kattis.com/problems/shortestpath1 2 | 3 | #include 4 | using namespace std; 5 | 6 | using ll = long long; 7 | 8 | #include "../../content/graphs/Dijkstra.h" 9 | 10 | int main() { 11 | cin.tie(0)->sync_with_stdio(0); 12 | cin.exceptions(cin.failbit); 13 | 14 | while (true) { 15 | int n, m, q, s; 16 | cin >> n >> m >> q >> s; 17 | 18 | if ((n | m | q | s) == 0) break; 19 | 20 | vector>> adj(n); 21 | 22 | for (int i = 0; i < m; i++) { 23 | int u, v, w; 24 | cin >> u >> v >> w; 25 | 26 | adj[u].emplace_back(v, w); 27 | } 28 | 29 | auto [reached, dist] = dijkstra(adj, s); 30 | 31 | for (int i = 0; i < q; i++) { 32 | int u; 33 | cin >> u; 34 | 35 | if (reached[u]) cout << dist[u] << '\n'; 36 | else 37 | cout << "Impossible\n"; 38 | } 39 | 40 | cout << '\n'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /content/data-structures/OrderStatisticTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2016-03-22 4 | * License: CC0 5 | * Source: hacKIT, NWERC 2015 6 | * Description: A set (not multiset!) with support for finding the n'th 7 | * element, and finding the index of an element. 8 | * To get a map, change \texttt{null\_type}. 9 | * Time: O(\log N) 10 | */ 11 | #pragma once 12 | #include /** keep-include */ 13 | usingnamespace __gnu_pbds; 14 | template 15 | using Tree = tree, rb_tree_tag, 16 | tree_order_statistics_node_update>; 17 | void example() { 18 | Tree t, t2; 19 | t.insert(8); 20 | auto it = t.insert(10).first; 21 | assert(it == t.lower_bound(9)); 22 | assert(t.order_of_key(10) == 1); 23 | assert(t.order_of_key(11) == 2); 24 | assert(*t.find_by_order(0) == 8); 25 | t.join(t2); // assuming T < T2 or T > T2, merge t2 into t 26 | } 27 | -------------------------------------------------------------------------------- /content/geometry/angleCmp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Andrew He 3 | * Date: 2019-03-15 4 | * License: CC0 5 | * Description: Useful utilities for dealing with angles of rays from origin. 6 | * OK for integers, only uses cross product. Doesn't support (0,0). 7 | */ 8 | #pragma once 9 | template bool sameDir(P s, P t) { 10 | return s.cross(t) == 0 && s.dot(t) > 0; } 11 | // checks 180 <= s..t < 360? 12 | template bool isReflex(P s, P t) { 13 | auto c = s.cross(t); 14 | return c ? (c < 0) : (s.dot(t) < 0); } 15 | // operator < (s,t) for angles in [base,base+2pi) 16 | template bool angleCmp(P base, P s, P t) { 17 | int r = isReflex(base, s) - isReflex(base, t); 18 | return r ? (r < 0) : (0 < s.cross(t)); } 19 | // is x in [s,t] taken ccw? 1/0/-1 for in/border/out 20 | template int angleBetween(P s, P t, P x) { 21 | if (sameDir(x, s) || sameDir(x, t)) return 0; 22 | return angleCmp(s, x, t) ? 1 : -1; } 23 | -------------------------------------------------------------------------------- /content/number-theory/CountPrimes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: lightseba 3 | * Description: Count primes in $O(N^\frac{3}{4})$. 4 | */ 5 | const int SQN = 320'000; 6 | bool notPrime[SQN]; 7 | ll countprimes(ll n) { 8 | vector divs; 9 | for (ll i = 1; i * i <= n; i++) { 10 | divs.push_back(i); 11 | divs.push_back(n / i); } 12 | sort(all(divs)); 13 | divs.erase(unique(all(divs)), end(divs)); 14 | vector dp(sz(divs)); 15 | for (int i = 0; i < sz(divs); i++) dp[i] = divs[i] - 1; 16 | ll sq = sqrt(n), sum = 0; 17 | auto idx = [&](ll x) -> int { 18 | return x <= sq ? x - 1 : (sz(divs) - n / x); }; 19 | for (ll p = 2; p * p <= n; p++) if (!notPrime[p]) { 20 | ll p2 = p * p; 21 | for (ll i = sz(divs) - 1; i >= 0 && divs[i] >= p2; i--) 22 | dp[i] -= dp[idx(divs[i] / p)] - sum; 23 | sum += 1; 24 | for (ll i = p * p; i < SQN && i * i <= n; i += p) 25 | notPrime[i] = 1; } 26 | return dp.back(); } 27 | -------------------------------------------------------------------------------- /content/crackpack/SteinerTrees.java: -------------------------------------------------------------------------------- 1 | // O(2^m * n^2 + 3^m * n) 2 | // precomp distances array 3 | // m is # of leaves; n is # of nodes 4 | int[][] dp = new int[n][1 << m]; 5 | for(int[] a : dp) Arrays.fill(a, oo); 6 | // Fill all leave's distances with their individual masks to 0 7 | for(int i = 0; i < m; i++) dp[ mapping[i] ][1 << i] = 0; 8 | for(int mask = 1; mask < (1 << m); mask++) 9 | for(int i = 0; i < n; i++) { 10 | for(int sm = mask; sm > 0; sm = (sm - 1) & mask) 11 | dp[i][mask] = Math.min(dp[i][mask], dp[i][sm] + dp[i][mask - sm]); 12 | for(int j = 0; j < n; j++) 13 | dp[j][mask] = Math.min(dp[j][mask], dp[i][mask] + dists[i][j]); 14 | } 15 | 16 | // Spiderman method for m <= 5 17 | // O( (v + e) * 2^m * log e ) 18 | // pick start leaf, do augmented dijkstra's on path 19 | // precomp distances from all leaves 20 | // state [i][leaves mask] = minCost 21 | // transition: either continue building path or grab some leaf 22 | -------------------------------------------------------------------------------- /content/data-structures/DSURestorable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Maintains union of disjoint sets, and can 3 | * revert to previous states. 4 | * Time: $O(\log{n})$ queries and unions, $O(\delta time)$ for restoring. 5 | */ 6 | struct RestorableDSU { 7 | vector s; 8 | vector> stk; 9 | RestorableDSU(int n): s(n, -1) {} 10 | int find(int i) { return s[i] < 0 ? i : find(s[i]); } 11 | bool join(int a, int b) { 12 | a = find(a), b = find(b); 13 | if (a == b) return false; 14 | if (s[a] > s[b]) swap(a, b); 15 | stk.emplace_back(a, s[a]); 16 | stk.emplace_back(b, s[b]); 17 | s[a] += s[b], s[b] = a; 18 | return true; } 19 | int time() { return stk.size(); } 20 | void revert(int t) { 21 | while (stk.size() > t) 22 | s[stk.back().first] = stk.back().second, stk.pop_back(); 23 | } 24 | int size(int i) { return -s[find(i)]; } 25 | bool same(int a, int b) { return find(a) == find(b); } }; 26 | -------------------------------------------------------------------------------- /content/numerical/SumOverSubsets.h: -------------------------------------------------------------------------------- 1 | // in place sum over subsets (give desc.) 2 | // works with vector, array, and std::array 3 | template void sos(Arr& f, int n, bool inv = 0) { 4 | for (int i = 0, b = 1; i < n; i++, b *= 2) 5 | rep(mask, 0, 1 << n) if (mask & b) f[mask] += 6 | inv ? -f[mask ^ b] : f[mask ^ b]; 7 | } 8 | template 9 | vector conv(const vector& a, const vector& b) { 10 | int n = __lg(sz(a)), len = 1 << n; 11 | vector> f(n + 1, vector(len)), g = f, h = f; 12 | rep(mask, 0, len) { 13 | int pc = __builtin_popcount(mask); 14 | f[pc][mask] = a[mask], g[pc][mask] = b[mask]; 15 | } 16 | rep(i, 0, n + 1) sos(f[i], n), sos(g[i], n); 17 | rep(mask, 0, len) rep(i, 0, n + 1) rep(j, 0, i + 1) 18 | h[i][mask] += f[j][mask] * g[i - j][mask]; 19 | rep(i, 0, n + 1) sos(h[i], n, 1); 20 | vector c(len); 21 | rep(mask, 0, len) c[mask] = 22 | h[__builtin_popcount(mask)][mask]; 23 | return c; 24 | } -------------------------------------------------------------------------------- /content/number-theory/MillerRabin.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: chilli, c1729, Simon Lindholm 3 | * Date: 2019-03-28 4 | * License: CC0 5 | * Source: Wikipedia, https://miller-rabin.appspot.com/ 6 | * Description: Deterministic Miller-Rabin primality test. 7 | * Guaranteed to work for numbers up to $7 \cdot 10^{18}$; for larger numbers, use Python and extend A randomly. 8 | * Time: 7 times the complexity of $a^b \mod c$. 9 | * Status: Stress-tested 10 | */ 11 | #pragma once 12 | #include "ModMulLL.h" 13 | bool isPrime(ull n) { 14 | if (n < 2 || n % 6 % 4 != 1) return (n | 1) == 3; 15 | ull A[] = {2, 325, 9375, 28178, 450775, 9780504, 16 | 1795265022}, s = __builtin_ctzll(n - 1), 17 | d = n >> s; 18 | for (ull a : A) { // ^ count trailing zeroes 19 | ull p = modpow(a % n, d, n), i = s; 20 | while (p != 1 && p != n - 1 && a % n && i--) 21 | p = modmul(p, p, n); 22 | if (p != n - 1 && i != s) return 0; } 23 | return 1; } 24 | -------------------------------------------------------------------------------- /content/data-structures/BIT.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Query [0, i) and [l, r) sums, and point updates. 3 | * kth() returns the smallest index i s.t. query(i) > k. 4 | * Right endpoint is exclusive. 5 | * Time: $O(\log n)$ for all ops. 6 | * Status: Tested 7 | */ 8 | template struct BIT { 9 | vector s; 10 | int n; 11 | BIT(int n): s(n + 1), n(n) {} 12 | void update(int i, T v) { 13 | for (i++; i <= n; i += i & -i) s[i] += v; } 14 | T query(int i) { // EXCLUSIVE interval [0, i) 15 | T ans = 0; 16 | for (; i; i -= i & -i) ans += s[i]; 17 | return ans; } // INCLUSIVE-EXCLUSIVE interval [l, r) 18 | // partial hash 2fe2e1 19 | T query(int l, int r) { return query(r) - query(l); } 20 | int kth(T k) { // 0-indexed, returns n if k > sum of tree 21 | if (k < 0) return -1; 22 | int i = 0; 23 | for (int pw = 1 << __lg(n); pw; pw >>= 1) 24 | if (i + pw <= n && s[i + pw] <= k) k -= s[i += pw]; 25 | return i; } }; 26 | -------------------------------------------------------------------------------- /content/numerical/IntegrateAdaptive.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2015-02-11 4 | * License: CC0 5 | * Source: Wikipedia 6 | * Description: Fast integration using an adaptive Simpson's rule. 7 | * Usage: 8 | double sphereVolume = quad(-1, 1, [](double x) { 9 | return quad(-1, 1, [\&](double y) { 10 | return quad(-1, 1, [\&](double z) { 11 | return x*x + y*y + z*z < 1; });});}); 12 | * Status: mostly untested 13 | */ 14 | #pragma once 15 | typedef double d; 16 | #define S(a, b) \ 17 | (f(a) + 4 * f((a + b) / 2) + f(b)) * (b - a) / 6 18 | template d rec(F& f, d a, d b, d eps, d S) { 19 | d c = (a + b) / 2; 20 | d S1 = S(a, c), S2 = S(c, b), T = S1 + S2; 21 | if (abs(T - S) <= 15 * eps || b - a < 1e-10) 22 | return T + (T - S) / 15; 23 | return rec(f, a, c, eps / 2, 24 | S1) + rec(f, c, b, eps / 2, S2); } 25 | template d quad(d a, d b, F f, d eps = 1e-8) { 26 | return rec(f, a, b, eps, S(a, b)); } 27 | -------------------------------------------------------------------------------- /content/number-theory/MultiplicativeSieve.h: -------------------------------------------------------------------------------- 1 | const int LIM = 1e6 + 10; 2 | vi primes; 3 | bitset notPrime; 4 | int ps[LIM], ks[LIM]; 5 | ll f[LIM]; 6 | template void sieve(int n = LIM) { 7 | f[1] = 1; 8 | for (int i = 2; i < n; i++) { 9 | if (!notPrime[i]) { 10 | primes.push_back(i); 11 | ps[i] = i, ks[i] = 1; 12 | f[i] = g(i, i, 1); 13 | for (ll pk = i, x = 1ll * i * i; x < n; 14 | pk *= i, x *= i) { 15 | ps[x] = x, ks[x] = ks[pk] + 1; 16 | f[x] = g(x, i, ks[x]); 17 | } 18 | } 19 | for (ll j = 0, p; 20 | j < sz(primes) && (p = primes[j]) * i < n; j++) { 21 | ll x = i * p; 22 | if (x >= n) break; 23 | notPrime[x] = 1; 24 | if (i % p == 0) { 25 | if (i != ps[i]) { 26 | ps[x] = ps[i] * p, ks[x] = ks[i] + 1; 27 | f[x] = f[i / ps[i]] * f[ps[x]]; 28 | } 29 | break; 30 | } else { 31 | f[x] = f[i] * f[p]; 32 | ps[x] = p, ks[x] = 1; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/data-structures/KDBIT.cpp: -------------------------------------------------------------------------------- 1 | // tested on https://www.spoj.com/problems/MATSUM/ 2 | #include 3 | using namespace std; 4 | 5 | using ll = long long; 6 | 7 | #include "../../content/data-structures/KDBIT.h" 8 | 9 | const int N = 1024; 10 | 11 | int main() { 12 | cin.tie(0)->sync_with_stdio(0); 13 | cin.exceptions(cin.failbit); 14 | 15 | int tests; 16 | cin >> tests; 17 | 18 | while (tests--) { 19 | int n; 20 | cin >> n; 21 | 22 | // this is too big for my stack locally 23 | BIT bit; 24 | 25 | while (true) { 26 | string t; 27 | cin >> t; 28 | 29 | if (t == "SET") { 30 | int x, y; 31 | ll d; 32 | cin >> x >> y >> d; 33 | 34 | ll old = bit.query(x, x, y, y); 35 | bit.update(x, y, d - old); 36 | } 37 | if (t == "SUM") { 38 | int x1, y1, x2, y2; 39 | cin >> x1 >> y1 >> x2 >> y2; 40 | cout << bit.query(x1, x2, y1, y2) << '\n'; 41 | } 42 | if (t == "END") break; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /content/data-structures/IterativeSegmentTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Lucian Bicsi 3 | * Date: 2017-10-31 4 | * License: CC0 5 | * Source: folklore 6 | * Description: Zero-indexed max-tree. Bounds are inclusive to the left and exclusive to the right. Can be changed by modifying T, f and unit. 7 | * Time: O(\log N) 8 | * Status: stress-tested 9 | */ 10 | #pragma once 11 | struct Tree { 12 | typedef int T; 13 | static constexpr T unit = INT_MIN; 14 | T f(T a, T b) { return max(a, b); } // (any associative fn) 15 | vector s; 16 | int n; 17 | Tree(int n = 0, T def = unit): s(2 * n, def), n(n) {} 18 | void update(int pos, T val) { 19 | for (s[pos += n] = val; pos /= 2; ) 20 | s[pos] = f(s[pos * 2], s[pos * 2 + 1]); } 21 | T query(int b, int e) { // query [b, e) 22 | T ra = unit, rb = unit; 23 | for (b += n, e += n; b < e; b /= 2, e /= 2) { 24 | if (b % 2) ra = f(ra, s[b++]); 25 | if (e % 2) rb = f(s[--e], rb); } 26 | return f(ra, rb); } }; 27 | -------------------------------------------------------------------------------- /content/geometry/lineDistance.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-03-21 4 | * License: CC0 5 | * Source: Basic math 6 | * Description:\\ 7 | \begin{minipage}{75mm} 8 | Returns the signed distance between point p and the line containing points a and b. Positive value on left side and negative on right as seen from a towards b. a==b gives nan. P is supposed to be Point or Point3D where T is e.g. double or long long. It uses products in intermediate steps so watch out for overflow if using int or long long. Using Point3D will always give a non-negative distance. For Point3D, call .dist on the result of the cross product. 9 | \end{minipage} 10 | \begin{minipage}{15mm} 11 | \includegraphics[width=\textwidth]{content/geometry/lineDistance} 12 | \end{minipage} 13 | * Status: tested 14 | */ 15 | #pragma once 16 | #include "Point.h" 17 | template 18 | double lineDist(const P& a, const P& b, const P& p) { 19 | return (double)(b - a).cross(p - a) / (b - a).dist(); } 20 | -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # echo "#lang format" > tmp.rkt 4 | # cat $1 >> tmp.rkt 5 | 6 | echo "Running formatter on $1" 7 | 8 | # racket /Users/seba/cp/format/format/run-direct.rkt $1 > formatted.h 9 | # /Users/seba/cp/format/run-direct $1 > formatted.h 10 | 11 | formatter="racket /Users/seba/cp/format/format/run-direct.rkt" 12 | 13 | if [ -f ./run-formatter ]; then 14 | formatter="./run-formatter" 15 | fi 16 | 17 | $formatter $1 > formatted.h 18 | 19 | if [[ $? -ne 0 ]]; then 20 | echo "Running formatter on $1 failed!" 21 | exit 22 | fi 23 | 24 | g++-13 -E -dD -P -fpreprocessed $1 2> /dev/null | tr -d '[:space:]' > orig.txt 25 | g++-13 -E -dD -P -fpreprocessed formatted.h 2> /dev/null | tr -d '[:space:]' > preproc.txt 26 | diff -w orig.txt preproc.txt 27 | 28 | if [[ $? -ne 0 ]]; then 29 | echo "Formatting changed diff for $1!" 30 | exit 31 | fi 32 | 33 | cp formatted.h $1 34 | 35 | rm formatted.h orig.txt preproc.txt 36 | 37 | echo "Successfully formatted $1!" -------------------------------------------------------------------------------- /content/geometry/circumcircle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-04-11 4 | * License: CC0 5 | * Source: http://en.wikipedia.org/wiki/Circumcircle 6 | * Description:\\ 7 | \begin{minipage}{75mm} 8 | The circumcirle of a triangle is the circle intersecting all three vertices. ccRadius returns the radius of the circle going through points A, B and C and ccCenter returns the center of the same circle. 9 | \end{minipage} 10 | \begin{minipage}{15mm} 11 | \vspace{-2mm} 12 | \includegraphics[width=\textwidth]{content/geometry/circumcircle} 13 | \end{minipage} 14 | * Status: tested 15 | */ 16 | #pragma once 17 | #include "Point.h" 18 | typedef Point P; 19 | double ccRadius(const P& A, const P& B, const P& C) { 20 | return (B - A).dist() * (C - B).dist() * (A - C).dist() / abs((B - A).cross(C - A)) / 2; 21 | } 22 | P ccCenter(const P& A, const P& B, const P& C) { 23 | P b = C - A, c = B - A; 24 | return A + (b * c.dist2() - c * b.dist2()).perp() / b.cross(c) / 2; 25 | } 26 | -------------------------------------------------------------------------------- /tests/data-structures/DSURestorable.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/persistent_unionfind" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/data-structures/DSURestorable.h" 4 | 5 | void test() { 6 | int n, q; 7 | cin >> n >> q; 8 | 9 | vector a(q + 1), b(q + 1), ans(q + 1, -1); 10 | vector> adj(q + 1); 11 | vector> qs(q + 1); 12 | 13 | for (int i = 1; i <= q; i++) { 14 | int t, k; 15 | cin >> t >> k >> a[i] >> b[i]; 16 | k++; 17 | 18 | if (t) qs[k].push_back(i); 19 | else 20 | adj[k].push_back(i); 21 | } 22 | 23 | RestorableDSU dsu(n); 24 | 25 | auto dfs = [&](int u, auto&& self) -> void { 26 | for (int i : qs[u]) ans[i] = dsu.same(a[i], b[i]); 27 | 28 | for (int v : adj[u]) { 29 | int t = dsu.time(); 30 | dsu.join(a[v], b[v]); 31 | self(v, self); 32 | dsu.revert(t); 33 | } 34 | }; 35 | 36 | dfs(0, dfs); 37 | 38 | for (int i : ans) 39 | if (i != -1) cout << i << '\n'; 40 | } 41 | -------------------------------------------------------------------------------- /content/math/Fraction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Struct for representing fractions/rationals. 3 | * All ops are $O(\log N)$ due to GCD in constructor. 4 | * Uses cross multiplication. 5 | */ 6 | template struct Q { 7 | T a, b; 8 | Q(T p, T q = 1) { 9 | T g = gcd(p, q); 10 | a = p / g; 11 | b = q / g; 12 | if (b < 0) a = -a, b = -b; } 13 | T gcd(T x, T y) const { return __gcd(x, y); } 14 | Q operator+(const Q& o) const { 15 | return {a * o.b + o.a * b, b * o.b}; } 16 | Q operator-(const Q& o) const { 17 | return *this + Q(-o.a, o.b); } 18 | Q operator*(const Q& o) const { return {a * o.a, b * o.b}; } 19 | Q operator/(const Q& o) const { 20 | return *this * Q(o.b, o.a); } 21 | Q recip() const { return {b, a}; } 22 | int signum() const { return (a > 0) - (a < 0); } 23 | bool operator<(const Q& o) const { 24 | return a * o.b < o.a * b; } 25 | friend ostream& operator<<(ostream& cout, const Q& o) { 26 | return cout << o.a << "/" << o.b; } }; 27 | -------------------------------------------------------------------------------- /content/number-theory/MultiplicativePrefixSum.h: -------------------------------------------------------------------------------- 1 | /* Prefix sum of multiplicative functions : 2 | p_f : the prefix sum of f (x) (1 <= x <= th). 3 | p_g : the prefix sum of g (x) (0 <= x <= N). 4 | p_c : the prefix sum of f * g (x) (0 <= x <= N). 5 | th : the thereshold, generally should be n ^ (2 / 3). 6 | */ 7 | typedef ll (*func)(ll); 8 | template 9 | struct prefix_mul { 10 | ll n, inv; 11 | unordered_map mem; 12 | ll calc(ll x) { 13 | if (x < TH) return p_f(x); 14 | auto it = mem.find(x); 15 | if (it != mem.end()) return it->second; 16 | ll ans = 0; 17 | for (ll i = 2, la; i <= x; i = la + 1) { 18 | la = x / (x / i); 19 | ans = 20 | (ans + (p_g(la) - p_g(i - 1) + mod) * calc(x / i)) % 21 | mod; 22 | } 23 | ans = (p_c(x) - ans + mod) * inv % mod; 24 | return mem[x] = ans; 25 | } 26 | ll solve(ll n) { 27 | if (n <= 0) return 0; 28 | this->n = n; 29 | inv = binpow(p_g(1), mod - 2); 30 | return calc(n); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /tests/graphs/TwoVertexCCs.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/two_edge_connected_components" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/graphs/TwoVertexCCs.h" 4 | #include "../../content/data-structures/DSU.h" 5 | 6 | void test() { 7 | int n, m; 8 | cin >> n >> m; 9 | 10 | ed.resize(n); 11 | vector edges(m); 12 | for (int i = 0; i < m; i++) { 13 | auto& [u, v] = edges[i]; 14 | cin >> u >> v; 15 | ed[u].emplace_back(v, i); 16 | ed[v].emplace_back(u, i); 17 | } 18 | 19 | DSU dsu(n); 20 | int ans = n; 21 | 22 | twoVCCs([&](const auto& cedges) { 23 | for (int i : cedges) { 24 | auto [u, v] = edges[i]; 25 | ans -= dsu.join(u, v); 26 | } 27 | }); 28 | 29 | vector out(n); 30 | for (int i = 0; i < n; i++) out[dsu.find(i)].push_back(i); 31 | 32 | cout << ans << "\n"; 33 | for (auto& it : out) { 34 | if (it.empty()) continue; 35 | cout << it.size() << " "; 36 | for (int i : it) cout << i << " "; 37 | cout << "\n"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/number-theory/MultiplicativePrefix.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/sum_of_totient_function" 2 | #include "../../tests/TestRunner.h" 3 | 4 | const ll mod = 998244353; 5 | ll binpow(ll a, ll n) { 6 | ll ans = 1; 7 | for (; n > 0; n /= 2, a = a * a % mod) 8 | if (n & 1) ans = a * ans % mod; 9 | return ans; 10 | } 11 | 12 | #include "../../content/number-theory/MultiplicativePrefixSum.h" 13 | #include "../../content/number-theory/MultiplicativeSieve.h" 14 | 15 | ll phi(int n, int p, int k) { return n / p * (p - 1); } 16 | ll p_phi(ll n) { return f[n]; } 17 | ll p_g(ll n) { return n % mod; } 18 | const ll inv2 = binpow(2, mod - 2); 19 | ll p_c(ll n) { 20 | n %= mod; 21 | return n * (n + 1) % mod * inv2 % mod; 22 | } 23 | 24 | void test() { 25 | sieve(); 26 | for (int i = 1; i < LIM; i++) { 27 | f[i] += f[i - 1]; 28 | if (f[i] >= mod) f[i] -= mod; 29 | } 30 | 31 | prefix_mul x; 32 | ll n; 33 | cin >> n; 34 | 35 | cout << x.solve(n) << "\n"; 36 | } 37 | -------------------------------------------------------------------------------- /content/data-structures/Matrix.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-08-03 4 | * License: CC0 5 | * Source: My head 6 | * Description: Basic operations on square matrices. 7 | * Usage: Matrix A; 8 | * A.d = {{{{1,2,3}}, {{4,5,6}}, {{7,8,9}}}}; 9 | * vector vec = {1,2,3}; 10 | * vec = (A^N) * vec; 11 | * Status: tested 12 | */ 13 | #pragma once 14 | template struct Matrix { 15 | typedef Matrix M; 16 | array, N> d{}; 17 | M operator*(const M& m) const { 18 | M a; 19 | rep (i, 0, N) rep (j, 0, N) rep (k, 0, N) 20 | a.d[i][j] += d[i][k] * m.d[k][j]; 21 | return a; } 22 | vector operator*(const vector& vec) const { 23 | vector ret(N); 24 | rep (i, 0, N) rep (j, 0, N) ret[i] += d[i][j] * vec[j]; 25 | return ret; } 26 | M operator^(ll p) const { 27 | assert(p >= 0); 28 | M a, b(*this); 29 | rep (i, 0, N) a.d[i][i] = 1; 30 | while (p) { if (p & 1) a = a * b; b = b * b; p >>= 1; } 31 | return a; } }; 32 | -------------------------------------------------------------------------------- /content/data-structures/SegTreeWalk.h: -------------------------------------------------------------------------------- 1 | // hash = 8f9536 2 | template int max_right(int l, G g) { // bool g(T); 3 | assert(g(e())); 4 | if (l == N) return N; 5 | l += S; 6 | for (int i = log; i >= 1; i--) push(l >> i); 7 | T sm = e(); 8 | do { 9 | while (l % 2 == 0) l >>= 1; 10 | if (!g(op(sm, d[l]))) { 11 | while (l < S) { 12 | push(l), l *= 2; 13 | if (g(op(sm, d[l]))) sm = op(sm, d[l++]); 14 | } 15 | return l - S; 16 | } 17 | sm = op(sm, d[l++]); 18 | } while ((l & -l) != l); 19 | return N; 20 | } 21 | template int min_left(int r, G g) { 22 | assert(g(e())); 23 | if (r == 0) return 0; 24 | r += S; 25 | for (int i = log; i >= 1; i--) push((r - 1) >> i); 26 | T sm = e(); 27 | do { 28 | r--; 29 | while (r > 1 && (r % 2)) r >>= 1; 30 | if (!g(op(d[r], sm))) { 31 | while (r < S) { 32 | push(r), r *= 2; 33 | if (g(op(d[++r], sm))) sm = op(d[r--], sm); 34 | } 35 | return r + 1 - S; 36 | } 37 | sm = op(d[r], sm); 38 | } while ((r & -r) != r); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /content/geometry/DelaunayTriangulation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Mattias de Zalenski 3 | * Date: Unknown 4 | * Source: Geometry in C 5 | * Description: Computes the Delaunay triangulation of a set of points. 6 | * Each circumcircle contains none of the input points. 7 | * If any three points are collinear or any four are on the same circle, behavior is undefined. 8 | * Time: O(n^2) 9 | * Status: stress-tested 10 | */ 11 | #pragma once 12 | #include "Point.h" 13 | #include "3dHull.h" 14 | template 15 | void delaunay(vector

& ps, F trifun) { 16 | if (sz(ps) == 3) { 17 | int d = (ps[0].cross(ps[1], ps[2]) < 0); 18 | trifun(0, 1 + d, 2 - d); } 19 | vector p3; 20 | for (P p : ps) p3.emplace_back(p.x, p.y, p.dist2()); 21 | if (sz(ps) > 3) for (auto t : hull3d(p3)) 22 | if ((p3[t.b] - p3[t.a]).cross(p3[t.c] - p3[t.a]).dot(P3(0, 23 | 0, 24 | 1)) < 0) 25 | trifun(t.a, t.c, t.b); } 26 | -------------------------------------------------------------------------------- /doc/scripts/compile-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | DIR=${1:-.} 3 | SCRIPT_DIR=$DIR/doc/scripts 4 | tests="$(find $DIR/content -name '*.h' | grep -vFf $SCRIPT_DIR/skip_headers)" 5 | echo "skipped: " 6 | find $DIR/content -name '*.h' | grep -Ff $SCRIPT_DIR/skip_headers 7 | declare -i pass=0 8 | declare -i fail=0 9 | failHeaders="" 10 | ulimit -s 524288 # For 2-sat test 11 | for test in $tests; do 12 | echo "$(basename $test): " 13 | $SCRIPT_DIR/test-compiles.sh $test 14 | retCode=$? 15 | if (($retCode != 0)); then 16 | echo $retCode 17 | fail+=1 18 | failHeaders="$failHeaders$test\n" 19 | else 20 | pass+=1 21 | fi 22 | rm -f a.out 23 | echo 24 | done 25 | echo "$pass/$(($pass+$fail)) tests passed" 26 | 27 | if (($pass == 0)); then 28 | echo "No tests found (make sure skip_headers doesn't have whitespace lines)" 29 | exit 1 30 | elif (($fail == 0)); then 31 | echo "No tests failed" 32 | exit 0 33 | else 34 | echo -e "These tests failed: \n $failHeaders" 35 | exit 1 36 | fi 37 | -------------------------------------------------------------------------------- /content/geometry/PointInsideHull.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: chilli 3 | * Date: 2019-05-17 4 | * License: CC0 5 | * Source: https://github.com/ngthanhtrung23/ACM_Notebook_new 6 | * Description: Determine whether a point t lies inside a convex hull (CCW 7 | * order, with no collinear points). Returns true if point lies within 8 | * the hull. If strict is true, points on the boundary aren't included. 9 | * Usage: 10 | * Status: stress-tested 11 | * Time: O(\log N) 12 | */ 13 | #pragma once 14 | #include "Point.h" 15 | #include "sideOf.h" 16 | #include "OnSegment.h" 17 | typedef Point P; 18 | bool inHull(const vector

& l, P p, bool strict = true) { 19 | int a = 1, b = sz(l) - 1, r = !strict; 20 | if (sz(l) < 3) return r && onSegment(l[0], l.back(), p); 21 | if (sideOf(l[0], l[a], l[b]) > 0) swap(a, b); 22 | if (sideOf(l[0], l[a], 23 | p) >= r || sideOf(l[0], l[b], p) <= -r) 24 | return false; 25 | while (abs(a - b) > 1) { 26 | int c = (a + b) / 2; 27 | (sideOf(l[0], l[c], p) > 0 ? b : a) = c; } 28 | return sgn(l[a].cross(l[b], p)) < r; } 29 | -------------------------------------------------------------------------------- /content/geometry/PolygonCut.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-03-21 4 | * License: CC0 5 | * Source: 6 | * Description:\\ 7 | \begin{minipage}{75mm} 8 | Returns a vector with the vertices of a polygon with everything to the left of the line going from s to e cut away. 9 | \end{minipage} 10 | \begin{minipage}{15mm} 11 | \vspace{-6mm} 12 | \includegraphics[width=\textwidth]{content/geometry/PolygonCut} 13 | \vspace{-6mm} 14 | \end{minipage} 15 | * Usage: 16 | * vector

p = ...; 17 | * p = polygonCut(p, P(0,0), P(1,0)); 18 | * Status: tested but not extensively 19 | */ 20 | #pragma once 21 | #include "Point.h" 22 | #include "lineIntersection.h" 23 | typedef Point P; 24 | vector

polygonCut(const vector

& poly, P s, P e) { 25 | vector

res; 26 | rep (i, 0, sz(poly)) { 27 | P cur = poly[i], prev = i ? poly[i - 1] : poly.back(); 28 | bool side = s.cross(e, cur) < 0; 29 | if (side != (s.cross(e, prev) < 0)) 30 | res.push_back(lineInter(s, e, cur, prev).second); 31 | if (side) res.push_back(cur); } 32 | return res; } 33 | -------------------------------------------------------------------------------- /content/graphs/GlobalMinCut.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2021-01-09 4 | * License: CC0 5 | * Source: https://en.wikipedia.org/wiki/Stoer%E2%80%93Wagner_algorithm 6 | * Description: Find a global minimum cut in an undirected graph, as represented by an adjacency matrix. 7 | * Time: O(V^3) 8 | * Status: Stress-tested together with GomoryHu 9 | */ 10 | #pragma once 11 | pair globalMinCut(vector mat) { 12 | pair best = {INT_MAX, {}}; 13 | int n = sz(mat); 14 | vector co(n); 15 | rep (i, 0, n) co[i] = {i}; 16 | rep (ph, 1, n) { 17 | vi w = mat[0]; 18 | size_t s = 0, t = 0; 19 | rep (it, 0, n - ph) { 20 | // O(V^2)->O(E log V) with prio. queue 21 | w[t] = INT_MIN; 22 | s = t, t = max_element(all(w)) - w.begin(); 23 | rep (i, 0, n) w[i] += mat[t][i]; } 24 | best = min(best, {w[t] - mat[t][t], co[t]}); 25 | co[s].insert(co[s].end(), all(co[t])); 26 | rep (i, 0, n) mat[s][i] += mat[t][i]; 27 | rep (i, 0, n) mat[i][s] = mat[s][i]; 28 | mat[0][t] = INT_MIN; } 29 | return best; } 30 | -------------------------------------------------------------------------------- /content/data-structures/KDBIT.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: $k$-dimensional BIT. \texttt{BIT} 3 | * gives an $N \times M$ BIT. Query \texttt{bit.query(x1, x2, y1, y2)} Update \texttt{bit.update(x, y, delta)} 4 | * Time: $O(\log^k n)$ 5 | * Status: Tested 6 | */ 7 | template struct BIT { 8 | T val = 0; 9 | void update(T v) { val += v; } 10 | T query() { return val; } 11 | }; 12 | template struct BIT { 13 | BIT bit[N + 1]; 14 | // map> bit; // if the mem use is too high 15 | template void update(int i, Args... args) { 16 | for (i++; i <= N; i += i & -i) bit[i].update(args...); 17 | } 18 | template T query(int i, Args... args) { 19 | T ans = 0; 20 | for (i++; i; i -= i & -i) ans += bit[i].query(args...); 21 | return ans; 22 | } 23 | template* = 25 | nullptr> 26 | T query(int l, int r, Args... args) { 27 | return query(r, args...) - query(l - 1, args...); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /content/crackpack/PolygonClipping.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | public class PolygonClipping { 4 | 5 | //only what is on side 1 of line will remain (positive cross product) 6 | static Vec[] clip(Vec[] poly, Seg line) { 7 | ArrayList toReturn=new ArrayList<>(); 8 | int nLeft=0, nRight=0, n=poly.length; 9 | int[] side=new int[n]; 10 | for (int i=0; i::iterator addInterval(set& is, int L, int R) { 12 | if (L == R) return is.end(); 13 | auto it = is.lower_bound({L, R}), before = it; 14 | while (it != is.end() && it->first <= R) { 15 | R = max(R, it->second); 16 | before = it = is.erase(it); } 17 | if (it != is.begin() && (--it)->second >= L) { 18 | L = min(L, it->first); 19 | R = max(R, it->second); 20 | is.erase(it); } 21 | return is.insert(before, {L, R}); } 22 | void removeInterval(set& is, int L, int R) { 23 | if (L == R) return; 24 | auto it = addInterval(is, L, R); 25 | auto r2 = it->second; 26 | if (it->first == L) is.erase(it); 27 | else (int&)it->second = L; 28 | if (R != r2) is.emplace(R, r2); } 29 | -------------------------------------------------------------------------------- /content/data-structures/MonotonicQueue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Queue that maintains its minimum/maximum element. 3 | * Time: Amortized $O(1)$ for $\texttt{push()}$, true 4 | * $O(1)$ for $\texttt{pop()}/\texttt{min()}$. 5 | * Usage: Works exactly like std::queue; 6 | * monotonic_queue gives a min queue, 7 | * and monotonic_queue> gives a max queue. 8 | */ 9 | template> 10 | struct monotonic_queue: queue { 11 | using q = queue; 12 | deque mq; 13 | Compare cmp; 14 | const T& min() { return assert(!q::empty()), mq.front(); } 15 | void update() { 16 | while (!mq.empty() && cmp(q::back(), mq.back())) 17 | mq.pop_back(); 18 | mq.push_back(q::back()); 19 | } 20 | void pop() { 21 | assert(!q::empty()); 22 | if (!mq.empty() && !cmp(mq.front(), q::front())) 23 | mq.pop_front(); 24 | q::pop(); 25 | } 26 | void push(const T& val) { queue::push(val), update(); } 27 | void push(T&& val) { queue::push(val), update(); } 28 | template void emplace(Args&&... args) { 29 | q::emplace(args...), update(); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /content/geometry/InsidePolygon.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Victor Lecomte, chilli 3 | * Date: 2019-04-26 4 | * License: CC0 5 | * Source: https://vlecomte.github.io/cp-geo.pdf 6 | * Description: Returns true if p lies within the polygon. If strict is true, 7 | * it returns false for points on the boundary. The algorithm uses 8 | * products in intermediate steps so watch out for overflow. 9 | * Time: O(n) 10 | * Usage: 11 | * vector

v = {P{4,4}, P{1,2}, P{2,1}}; 12 | * bool in = inPolygon(v, P{3, 3}, false); 13 | * Status: stress-tested and tested on kattis:pointinpolygon 14 | */ 15 | #pragma once 16 | #include "Point.h" 17 | #include "OnSegment.h" 18 | #include "SegmentDistance.h" 19 | template 20 | bool inPolygon(vector

& p, P a, bool strict = true) { 21 | int cnt = 0, n = sz(p); 22 | rep (i, 0, n) { 23 | P q = p[(i + 1) % n]; 24 | if (onSegment(p[i], q, a)) return !strict; 25 | //or: if (segDist(p[i], q, a) <= eps) return !strict; 26 | cnt ^= ((a.y < p[i].y) - (a.y < q.y)) * a.cross(p[i], 27 | q) > 0; } 28 | return cnt; } 29 | -------------------------------------------------------------------------------- /content/graphs/SCCKosaraju.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Finds strongly connected components of a 3 | * directed graph. Visits/indexes SCCs in 4 | * topological order. 5 | * Time: $O(|V| + |E|)$ 6 | * Usage: scc(graph) returns an array that has the ID 7 | * of each node's SCC. 8 | */ 9 | namespace SCCKosaraju { 10 | vector> adj, radj; 11 | vector todo, comp; 12 | vector vis; 13 | void dfs1(int x) { 14 | vis[x] = 1; 15 | for (int y : adj[x]) 16 | if (!vis[y]) dfs1(y); 17 | todo.push_back(x); 18 | } 19 | void dfs2(int x, int i) { 20 | comp[x] = i; 21 | for (int y : radj[x]) 22 | if (comp[y] == -1) dfs2(y, i); 23 | } 24 | vector scc(vector>& _adj) { 25 | adj = _adj; 26 | int time = 0, n = adj.size(); 27 | comp.resize(n, -1), radj.resize(n), vis.resize(n); 28 | for (int x = 0; x < n; x++) 29 | for (int y : adj[x]) radj[y].push_back(x); 30 | for (int x = 0; x < n; x++) 31 | if (!vis[x]) dfs1(x); 32 | reverse(todo.begin(), todo.end()); 33 | for (int x : todo) 34 | if (comp[x] == -1) dfs2(x, time++); 35 | return comp; 36 | } 37 | }; // namespace SCCKosaraju 38 | -------------------------------------------------------------------------------- /content/graphs/MaximalCliques.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2018-07-18 4 | * License: CC0 5 | * Source: https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm 6 | * Description: Runs a callback for all maximal cliques in a graph (given as a 7 | * symmetric bitset matrix; self-edges not allowed). Callback is given a bitset 8 | * representing the maximal clique. 9 | * Time: O(3^{n/3}), much faster for sparse graphs 10 | * Status: stress-tested 11 | */ 12 | #pragma once /// Possible optimization: on the top-most /// recursion level, ignore 'cands', and go through nodes in order of increasing 13 | /// degree, where degrees go down as nodes are removed. 14 | /// (mostly irrelevant given MaximumClique) 15 | typedef bitset<128> B; 16 | template 17 | void 18 | cliques(vector& eds, F f, B P = ~B(), B X = {}, B R = {}) { 19 | if (!P.any()) { if (!X.any()) f(R); return; } 20 | auto q = (P | X)._Find_first(); 21 | auto cands = P & ~eds[q]; 22 | rep (i, 0, sz(eds)) if (cands[i]) { 23 | R[i] = 1; 24 | cliques(eds, f, P & eds[i], X & eds[i], R); 25 | R[i] = P[i] = 0; 26 | X[i] = 1; } } 27 | -------------------------------------------------------------------------------- /tests/data-structures/LiChaoTree.test.cpp: -------------------------------------------------------------------------------- 1 | #define PROBLEM "https://judge.yosupo.jp/problem/range_chmin_chmax_add_range_sum" 2 | #include "../../tests/TestRunner.h" 3 | #include "../../content/data-structures/LiChaoTree.h" 4 | 5 | const ll XV = ll(1e9) + 10; 6 | const ll oo = ll(2e18) + 100; 7 | 8 | ll eval(pair p, ll x) { return p.first*x + p.second; } 9 | pair big() { return {XV, oo}; } 10 | 11 | void test() { 12 | int n, q; 13 | cin >> n >> q; 14 | 15 | LiChao, big, eval> t(-XV, XV); 16 | 17 | rep (_, 0, n) { 18 | ll l, r, a, b; 19 | cin >> l >> r >> a >> b; 20 | t.update(l, r, {a, b}); 21 | } 22 | 23 | rep (_, 0, q) { 24 | int qt; 25 | cin >> qt; 26 | 27 | if (qt == 0) { 28 | ll l, r, a, b; 29 | cin >> l >> r >> a >> b; 30 | t.update(l, r, {a, b}); 31 | } 32 | else { 33 | ll p; 34 | cin >> p; 35 | auto res = t.query(p); 36 | if (res >= oo / 2) cout << "INFINITY\n"; 37 | else cout << res << "\n"; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /content/geometry/sphericalDistance.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-04-07 4 | * License: CC0 5 | * Source: My geometric reasoning 6 | * Description: Returns the shortest distance on the sphere with radius radius between the points with azimuthal angles (longitude) f1 ($\phi_1$) and f2 ($\phi_2$) from x axis and zenith angles (latitude) t1 ($\theta_1$) and t2 ($\theta_2$) from z axis (0 = north pole). All angles measured in radians. The algorithm starts by converting the spherical coordinates to cartesian coordinates so if that is what you have you can use only the two last rows. dx*radius is then the difference between the two points in the x direction and d*radius is the total distance between the points. 7 | * Status: tested on kattis:airlinehub 8 | */ 9 | #pragma once 10 | double sphericalDistance(double f1, double t1, double f2, 11 | double t2, double radius) { 12 | double dx = sin(t2) * cos(f2) - sin(t1) * cos(f1); 13 | double dy = sin(t2) * sin(f2) - sin(t1) * sin(f1); 14 | double dz = cos(t2) - cos(t1); 15 | double d = sqrt(dx * dx + dy * dy + dz * dz); 16 | return radius * 2 * asin(d / 2); } 17 | -------------------------------------------------------------------------------- /doc/scripts/inline_includes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # from https://github.com/AlexeyDmitriev/inline_includes 3 | import sys 4 | import os 5 | import os.path 6 | 7 | USED = set() 8 | INCLUDE_PATHS = None 9 | 10 | 11 | def include_target(file, path): 12 | for include_path in [os.path.dirname(file), *INCLUDE_PATHS]: 13 | candidate = os.path.join(include_path, path) 14 | if os.path.isfile(candidate): 15 | return candidate 16 | return None 17 | 18 | 19 | def dfs(file): 20 | if file in USED: 21 | return 22 | USED.add(file) 23 | with open(file, "r") as f: 24 | for line in f: 25 | if line.startswith("#include "): 26 | path = include_target(file, line[8:].strip("\n\r \"<>")) 27 | if path is not None: 28 | dfs(path) 29 | else: 30 | print(line, end='') 31 | else: 32 | print(line, end='') 33 | 34 | 35 | def main(): 36 | global INCLUDE_PATHS 37 | INCLUDE_PATHS = sys.argv[:-1] 38 | dfs(sys.argv[-1]) 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /content/kactl.tex: -------------------------------------------------------------------------------- 1 | \documentclass[9pt, a4paper, notitlepage]{extreport} 2 | \usepackage{kactlpkg} 3 | \kactlcontentdir{content} 4 | 5 | \university{UCF Cactus}{University of Central Florida}{TheTab_KGcmyk} 6 | \team{UCF Cactus}{Jacob Magnuson, Seba Villalobos, Daniel West} 7 | \contest{2022 ICPC World Finals}{April 18, 2024} 8 | % \contest{\ }{\today} 9 | % \enablecolors 10 | 11 | \begin{document} 12 | \maketeampage 13 | % Small KACTL header on the first page: 14 | % \maketitle{``One Last Time'' Edition}{\today} 15 | \begin{multicols*}{3} 16 | \thispagestyle{fancy} 17 | % Table of contents, without subsections: 18 | \setcounter{tocdepth}{0} 19 | \tableofcontents 20 | 21 | \kactlchapter{contest} 22 | \kactlchapter{data-structures} 23 | \kactlchapter{geometry} 24 | \kactlchapter{graphs} 25 | \kactlchapter{strings} 26 | \kactlchapter{misc} 27 | \kactlchapter{math} 28 | \kactlchapter{combinatorial} 29 | \kactlchapter{number-theory} 30 | \kactlchapter{numerical} 31 | % \kactlchapter{solutions} 32 | % \kactlchapter{crackpack} 33 | 34 | \end{multicols*} 35 | 36 | % \begin{multicols*}{3} 37 | % \kactlchapter{appendix} 38 | % \end{multicols*} 39 | \end{document} 40 | -------------------------------------------------------------------------------- /content/number-theory/phiFunction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Håkan Terelius 3 | * Date: 2009-09-25 4 | * License: CC0 5 | * Source: http://en.wikipedia.org/wiki/Euler's_totient_function 6 | * Description: \emph{Euler's $\phi$} function is defined as $\phi(n):=\#$ of positive integers $\leq n$ that are coprime with $n$. 7 | * $\phi(1)=1$, $p$ prime $\Rightarrow \phi(p^k)=(p-1)p^{k-1}$, $m,n$ coprime $\Rightarrow \phi(mn)=\phi(m)\phi(n)$. 8 | * If $n=p_1^{k_1}p_2^{k_2} ... p_r^{k_r}$ then $\phi(n) = (p_1-1)p_1^{k_1-1}...(p_r-1)p_r^{k_r-1}$. 9 | * $\phi(n)=n \cdot \prod_{p|n}(1-1/p)$. 10 | * 11 | * $\sum_{d|n} \phi(d) = n$, $\sum_{1\leq k \leq n, \gcd(k,n)=1} k = n \phi(n)/2, n>1$ 12 | * 13 | * \textbf{Euler's thm}: $a,n$ coprime $\Rightarrow a^{\phi(n)} \equiv 1 \pmod{n}$. 14 | * 15 | * \textbf{Fermat's little thm}: $p$ prime $\Rightarrow a^{p-1} \equiv 1 \pmod{p}$ $\forall a$. 16 | * Status: Tested 17 | */ 18 | #pragma once 19 | const int LIM = 5000000; 20 | int phi[LIM]; 21 | void calculatePhi() { 22 | rep (i, 0, LIM) phi[i] = i & 1 ? i : i / 2; 23 | for (int i = 3; i < LIM; i += 2) if (phi[i] == i) 24 | for (int j = i; j < LIM; j += i) phi[j] -= phi[j] / i; } 25 | -------------------------------------------------------------------------------- /content/geometry/ConvexHull.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Stjepan Glavina, chilli 3 | * Date: 2019-05-05 4 | * License: Unlicense 5 | * Source: https://github.com/stjepang/snippets/blob/master/convex_hull.cpp 6 | * Description: 7 | \\\begin{minipage}{75mm} 8 | Returns a vector of the points of the convex hull in counter-clockwise order. 9 | Points on the edge of the hull between two other points are not considered part of the hull. 10 | \end{minipage} 11 | \begin{minipage}{15mm} 12 | \vspace{-6mm} 13 | \includegraphics[width=\textwidth]{content/geometry/ConvexHull} 14 | \vspace{-6mm} 15 | \end{minipage} 16 | * Time: O(n \log n) 17 | * Status: stress-tested, tested with kattis:convexhull 18 | */ 19 | #pragma once 20 | #include "Point.h" 21 | typedef Point P; 22 | vector

convexHull(vector

pts) { 23 | if (sz(pts) <= 1) return pts; 24 | sort(all(pts)); 25 | vector

h(sz(pts) + 1); 26 | int s = 0, t = 0; 27 | for (int it = 2; it--; s = --t, reverse(all(pts))) 28 | for (P p : pts) { 29 | while (t >= s + 2 && h[t - 2].cross(h[t - 1], p) <= 0) 30 | t--; 31 | h[t++] = p; } 32 | return {h.begin(), 33 | h.begin() + t - (t == 2 && h[0] == h[1])}; } 34 | -------------------------------------------------------------------------------- /content/numerical/FastSubsetTransform.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Lucian Bicsi 3 | * Date: 2015-06-25 4 | * License: GNU Free Documentation License 1.2 5 | * Source: csacademy 6 | * Description: Transform to a basis with fast convolutions of the form 7 | * $\displaystyle c[z] = \sum\nolimits_{z = x \oplus y} a[x] \cdot b[y]$, 8 | * where $\oplus$ is one of AND, OR, XOR. The size of $a$ must be a power of two. 9 | * Time: O(N \log N) 10 | * Status: stress-tested 11 | */ 12 | #pragma once 13 | void FST(vi& a, bool inv) { 14 | for (int n = sz(a), step = 1; step < n; step *= 2) { 15 | for (int i = 0; i < n; i += 2 * step) rep (j, 16 | i, i + step) { 17 | int& u = a[j], &v = a[j + step]; 18 | tie(u, v) = inv ? pii(v - u, u) : pii(v, u + v); // AND 19 | // inv ? pii(v, u - v) : pii(u + v, u); // OR /// include-line 20 | // pii(u + v, u - v); // XOR /// include-line 21 | } } 22 | // if (inv) for (int& x : a) x /= sz(a); // XOR only /// include-line 23 | } 24 | vi conv(vi a, vi b) { 25 | FST(a, 0); 26 | FST(b, 0); 27 | rep (i, 0, sz(a)) a[i] *= b[i]; 28 | FST(a, 1); 29 | return a; } 30 | -------------------------------------------------------------------------------- /tests/data-structures/MonotonicQueue.cpp: -------------------------------------------------------------------------------- 1 | // Tested on NEERC 2015 Northern: Journey to the "The World's 2 | // Start" https://codeforces.com/gym/100801 3 | #include 4 | #define all(x) begin(x), end(x) 5 | using namespace std; 6 | using ll = long long; 7 | 8 | #include "../../content/data-structures/MonotonicQueue.h" 9 | 10 | int main() { 11 | cin.tie(0)->sync_with_stdio(0); 12 | cin.exceptions(cin.failbit); 13 | freopen("journey.in", "r", stdin); 14 | freopen("journey.out", "w", stdout); 15 | 16 | int n; 17 | ll t; 18 | cin >> n >> t; 19 | 20 | vector p(n), d(n); 21 | 22 | for (int i = 1; i < n; i++) cin >> p[i]; 23 | for (int i = 1; i < n - 1; i++) cin >> d[i]; 24 | 25 | auto go = [&](int r) { 26 | monotonic_queue q; 27 | q.push(0); 28 | 29 | for (int i = n - 2; i >= 0; i--) { 30 | q.push(d[i] + q.min()); 31 | while (q.size() > r) q.pop(); 32 | } 33 | 34 | return q.back() + n - 1; 35 | }; 36 | 37 | int lo = 1, hi = n - 1; 38 | while (lo < hi) { 39 | int mid = (lo + hi) / 2; 40 | 41 | if (go(mid) <= t) hi = mid; 42 | else 43 | lo = mid + 1; 44 | } 45 | 46 | cout << *min_element(p.begin() + hi, p.end()) << '\n'; 47 | } 48 | -------------------------------------------------------------------------------- /tests/graphs/Dijkstra_NAQC.cpp: -------------------------------------------------------------------------------- 1 | // Tested on https://open.kattis.com/problems/bigtruck 2 | 3 | #include 4 | using namespace std; 5 | 6 | using ll = long long; 7 | 8 | #include "../../content/graphs/Dijkstra.h" 9 | 10 | struct Weight { 11 | ll d, it; 12 | Weight(ll d = 0, ll it = 0): d(d), it(it) {} 13 | Weight operator+(const Weight& o) const { return {d + o.d, it + o.it}; } 14 | bool operator<(const Weight& o) const { return d < o.d || (d == o.d && it > o.it); } 15 | }; 16 | 17 | int main() { 18 | cin.tie(0)->sync_with_stdio(0); 19 | cin.exceptions(cin.failbit); 20 | 21 | int n; 22 | cin >> n; 23 | 24 | vector items(n); 25 | vector>> adj(n); 26 | 27 | for (int& x : items) cin >> x; 28 | 29 | int m; 30 | cin >> m; 31 | for (int i = 0; i < m; i++) { 32 | int u, v, w; 33 | cin >> u >> v >> w; 34 | u--, v--; 35 | 36 | adj[u].emplace_back(v, Weight(w, items[v])); 37 | adj[v].emplace_back(u, Weight(w, items[u])); 38 | } 39 | 40 | auto [reached, dist] = dijkstra(adj, 0); 41 | 42 | if (!reached[n - 1]) cout << "impossible\n"; 43 | else 44 | cout << dist[n - 1].d << " " << dist[n - 1].it + items[0] << "\n"; 45 | } 46 | -------------------------------------------------------------------------------- /tests/data-structures/DSURestorable.cpp: -------------------------------------------------------------------------------- 1 | // tested on Library-Checker: Persistent UnionFind 2 | // https://judge.yosupo.jp/problem/persistent_unionfind 3 | #include 4 | #define all(x) begin(x), end(x) 5 | using namespace std; 6 | 7 | using ll = long long; 8 | 9 | #include "../../content/data-structures/DSURestorable.h" 10 | 11 | int main() { 12 | cin.tie(0)->sync_with_stdio(0); 13 | cin.exceptions(cin.failbit); 14 | 15 | int n, q; 16 | cin >> n >> q; 17 | 18 | vector a(q + 1), b(q + 1), ans(q + 1, -1); 19 | vector> adj(q + 1); 20 | vector> qs(q + 1); 21 | 22 | for (int i = 1; i <= q; i++) { 23 | int t, k; 24 | cin >> t >> k >> a[i] >> b[i]; 25 | k++; 26 | 27 | if (t) qs[k].push_back(i); 28 | else 29 | adj[k].push_back(i); 30 | } 31 | 32 | RestorableDSU dsu(n); 33 | 34 | auto dfs = [&](int u, auto&& self) -> void { 35 | for (int i : qs[u]) ans[i] = dsu.same(a[i], b[i]); 36 | 37 | for (int v : adj[u]) { 38 | int t = dsu.time(); 39 | dsu.join(a[v], b[v]); 40 | self(v, self); 41 | dsu.revert(t); 42 | } 43 | }; 44 | 45 | dfs(0, dfs); 46 | 47 | for (int i : ans) 48 | if (i != -1) cout << i << '\n'; 49 | } 50 | -------------------------------------------------------------------------------- /content/graphs/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Graphs} 2 | Euler's planar graph formula: $V - E + F - C = 1$ 3 | \kactlimport{SCCTarjan.h} 4 | \kactlimport{2sat.h} 5 | % \kactlimport{SCCKosaraju.h} 6 | \kactlimport{EulerWalk.h} 7 | % \kactlimport{Dijkstra.h} 8 | \kactlimport{MaximumClique.h} 9 | \kactlimport{MaximalCliques.h} 10 | \kactlimport{EdgeColoring.h} 11 | \kactlimport{DirectedMST.h} 12 | \kactlimport{DominatorTree.h} 13 | 14 | \section{Trees} 15 | \kactlimport{LCA.h} 16 | \kactlimport{HLD.h} 17 | \kactlimport{TreeLifting.h} 18 | % \kactlimport{CentroidDecomposition.java} 19 | \kactlimport{TwoEdgeCCs.h} 20 | \kactlimport{TwoVertexCCs.h} 21 | \kactlimport{2VCCs.h} 22 | \kactlimport{CompressTree.h} 23 | 24 | \section{Flow} 25 | \kactlimport{hopcroftKarp.h} 26 | \kactlimport{WeightedMatching.h} 27 | \kactlimport{SebaDinic.h} 28 | % \kactlimport{KactlDinic.h} 29 | \kactlimport{PushRelabel.h} 30 | \kactlimport{MinCostMaxFlow.h} 31 | % \kactlimport{javamcmf.h} 32 | \kactlimport{GlobalMinCut.h} 33 | % \kactlimport{GeneralMatching.h} 34 | \kactlimport{Blossom.h} 35 | \kactlimport{GomoryHu.h} 36 | \kactlimport{MatroidIntersection.h} 37 | -------------------------------------------------------------------------------- /content/graphs/CompressTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2016-01-14 4 | * License: CC0 5 | * Description: Given a rooted tree and a subset S of nodes, compute the minimal 6 | * subtree that contains all the nodes by adding all (at most $|S|-1$) 7 | * pairwise LCA's and compressing edges. 8 | * Returns a list of (par, orig\_index) representing a tree rooted at 0. 9 | * The root points to itself. 10 | * Time: $O(|S| \log |S|)$ 11 | * Status: Tested at CodeForces 12 | */ 13 | #pragma once 14 | #include "LCA.h" 15 | typedef vector> vpi; 16 | vpi compressTree(LCA& lca, const vi& subset) { 17 | static vi rev; 18 | rev.resize(sz(lca.time)); 19 | vi li = subset, &T = lca.time; 20 | auto cmp = [&](int a, int b) { return T[a] < T[b]; }; 21 | sort(all(li), cmp); 22 | int m = sz(li) - 1; 23 | rep (i, 0, m) { 24 | int a = li[i], b = li[i + 1]; 25 | li.push_back(lca.lca(a, b)); } 26 | sort(all(li), cmp); 27 | li.erase(unique(all(li)), li.end()); 28 | rep (i, 0, sz(li)) rev[li[i]] = i; 29 | vpi ret = {pii(0, li[0])}; 30 | rep (i, 0, sz(li) - 1) { 31 | int a = li[i], b = li[i + 1]; 32 | ret.emplace_back(rev[lca.lca(a, b)], b); } 33 | return ret; } 34 | -------------------------------------------------------------------------------- /content/geometry/HullTangents.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: marks39, Meaf, lightseba 3 | * Date: 2023-02-10 4 | * Description: Finds the left and right, respectively, tangent 5 | * points on convex hull from a point. If the point is colinear 6 | * to side(s) of the polygon, the point further away is 7 | * returned. Requires ccw, $n \geq 3$, and the point be on or 8 | * outside the polygon. 9 | * Time: O(\log n) 10 | * Status: tested on ASC 40: A and SER 2016: D 11 | */ 12 | #pragma once 13 | #include "Point.h" 14 | #define cmp(i, j) p.cross(h[i], h[j == n ? 0 : j]) * (R ?: -1) 15 | template int getTangent(vector

& h, P p) { 16 | int n = sz(h), lo = 0, hi = n - 1, md; 17 | if (cmp(0, 1) >= R && cmp(0, n - 1) >= !R) return 0; 18 | while (md = (lo + hi + 1) / 2, lo < hi) { 19 | auto a = cmp(md, md + 1), b = cmp(md, lo); 20 | if (a >= R && cmp(md, md - 1) >= !R) return md; 21 | if (cmp(lo, lo + 1) < R) 22 | a < R && b >= 0 ? lo = md : hi = md - 1; 23 | else a < R || b <= 0 ? lo = md : hi = md - 1; } 24 | return -1; // point strictly inside hull 25 | } 26 | template pii hullTangents(vector

& h, P p) { 27 | return {getTangent<0 > (h, p), getTangent < 1>(h, p)}; } 28 | -------------------------------------------------------------------------------- /content/graphs/EulerWalk.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2019-12-31 4 | * License: CC0 5 | * Source: folklore 6 | * Description: Eulerian undirected/directed path/cycle algorithm. 7 | * Input should be a vector of (dest, global edge index), where 8 | * for undirected graphs, forward/backward edges have the same index. 9 | * Returns a list of nodes in the Eulerian path/cycle with src at both start and end, or 10 | * empty list if no cycle/path exists. 11 | * To get edge indices back, add .second to s and ret. 12 | * Time: O(V + E) 13 | * Status: stress-tested 14 | */ 15 | #pragma once 16 | vi 17 | eulerWalk(vector>& gr, int nedges, int src = 0) { 18 | int n = sz(gr); 19 | vi D(n), its(n), eu(nedges), ret, s = {src}; 20 | D[src]++; // to allow Euler paths, not just cycles 21 | while (!s.empty()) { 22 | int x = s.back(), y, e, &it = its[x], end = sz(gr[x]); 23 | if (it == end) { 24 | ret.push_back(x), s.pop_back(); 25 | continue; } 26 | tie(y, e) = gr[x][it++]; 27 | if (!eu[e]) { D[x]--, D[y]++; eu[e] = 1, s.push_back(y); } 28 | } 29 | for (int x : D) if (x < 0 || sz(ret) != nedges + 1) 30 | return {}; 31 | return {ret.rbegin(), ret.rend()}; } 32 | -------------------------------------------------------------------------------- /content/geometry/CirclePolygonIntersection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: chilli, Takanori MAEHARA 3 | * Date: 2019-10-31 4 | * License: CC0 5 | * Source: https://github.com/spaghetti-source/algorithm/blob/master/geometry/_geom.cc#L744 6 | * Description: Returns the area of the intersection of a circle with a 7 | * ccw polygon. 8 | * Time: O(n) 9 | * Status: Tested on GNYR 2019 Gerrymandering, stress-tested 10 | */ 11 | #pragma once 12 | #include "../../content/geometry/Point.h" 13 | typedef Point P; 14 | #define arg(p, q) atan2(p.cross(q), p.dot(q)) 15 | double circlePoly(P c, double r, vector

ps) { 16 | auto tri = [&](P p, P q) { 17 | auto r2 = r * r / 2; 18 | P d = q - p; 19 | auto a = d.dot(p) / d.dist2(), 20 | b = (p.dist2() - r * r) / d.dist2(); 21 | auto det = a * a - b; 22 | if (det <= 0) return arg(p, q) * r2; 23 | auto s = max(0., -a - sqrt(det)), 24 | t = min(1., -a + sqrt(det)); 25 | if (t < 0 || 1 <= s) return arg(p, q) * r2; 26 | P u = p + d * s, v = p + d * t; 27 | return arg(p, u) * r2 + u.cross(v) / 2 + arg(v, q) * r2; 28 | }; 29 | auto sum = 0.0; 30 | rep (i, 0, sz(ps)) 31 | sum += tri(ps[i] - c, ps[(i + 1) % sz(ps)] - c); 32 | return sum; } 33 | -------------------------------------------------------------------------------- /content/geometry/CircleTangents.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Victor Lecomte, chilli 3 | * Date: 2019-10-31 4 | * License: CC0 5 | * Source: https://vlecomte.github.io/cp-geo.pdf 6 | * Description: Finds the external tangents of two circles, or internal if r2 is negated. 7 | * Can return 0, 1, or 2 tangents -- 0 if one circle contains the other (or overlaps it, in the internal case, or if the circles are the same); 8 | * 1 if the circles are tangent to each other (in which case .first = .second and the tangent line is perpendicular to the line between the centers). 9 | * .first and .second give the tangency points at circle 1 and 2 respectively. 10 | * To find the tangents of a circle with a point set r2 to 0. 11 | * Status: tested 12 | */ 13 | #pragma once 14 | #include "Point.h" 15 | template 16 | vector> 17 | tangents(P c1, double r1, P c2, double r2) { 18 | P d = c2 - c1; 19 | double dr = r1 - r2, d2 = d.dist2(), h2 = d2 - dr * dr; 20 | if (d2 == 0 || h2 < 0) return {}; 21 | vector> out; 22 | for (double sign : {-1, 1}) { 23 | P v = (d * dr + d.perp() * sqrt(h2) * sign) / d2; 24 | out.push_back({c1 + v * r1, c2 + v * r2}); } 25 | if (h2 == 0) out.pop_back(); 26 | return out; } 27 | -------------------------------------------------------------------------------- /content/geometry/mitlineIntersection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-03-21 4 | * License: CC0 5 | * Source: 6 | * Description: If a unique intersection point of the lines going through s1,e1 and s2,e2 exists r is set to this point and 1 is returned. If no intersection point exists 0 is returned and if infinitely many exists -1 is returned. If s1==e1 or s2==e2 -1 is returned. The wrong position will be returned if P is Point and the intersection point does not have integer coordinates. Products of three coordinates are used in intermediate steps so watch out for overflow if using int or long long. 7 | * Status: tested 8 | * Usage: 9 | * point intersection; 10 | * if (1 == LineIntersection(s1,e1,s2,e2,intersection)) 11 | * cout << "intersection point at " << intersection << endl; 12 | */ 13 | #pragma once 14 | #include "Point.h" 15 | template 16 | int lineIntersection(const P& s1, const P& e1, const P& s2, 17 | const P& e2, P& r) { 18 | if ((e1 - s1).cross(e2 - s2)) { //if not parallell 19 | r = s2 - (e2 - s2) * (e1 - s1).cross(s2 - s1) / (e1 - s1).cross(e2 - s2); 20 | return 1; } 21 | else return -((e1 - s1).cross(s2 - s1) == 0 || s2 == e2); } 22 | -------------------------------------------------------------------------------- /content/graphs/TreeLifting.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: lightseba 3 | * Date: 2022-04-12 4 | * License: CC0 5 | * Source: https://codeforces.com/blog/entry/100826 6 | * Description: Calculate jumps up a tree, 7 | * to support fast upward jumps and LCAs. 8 | * Assumes the root node points to itself. 9 | * Time: construction $O(N)$, queries $O(\log N)$ 10 | * Status: Tested 11 | */ 12 | #pragma once 13 | struct lift { 14 | vi d, p, j; 15 | lift(vector& adj): d(sz(adj)), p(d), j(d) { 16 | dfs(0, adj); } 17 | void dfs(int u, vector& adj) { 18 | int jmp = (d[u] + d[j[j[u]]] == 2 * d[j[u]]) ? j[j[u]] 19 | : u; 20 | for (int v : adj[u]) if (v != p[u]) 21 | d[v] = d[p[v] = u] + 1, j[v] = jmp, dfs(v, adj); } 22 | int lca(int u, int v) { 23 | if (d[u] < d[v]) swap(u, v); 24 | while (d[u] > d[v]) u = d[j[u]] >= d[v] ? j[u] : p[u]; 25 | if (u == v) return u; 26 | while (p[u] != p[v]) if (j[u] != j[v]) u = j[u], v = j[v]; 27 | else u = p[u], v = p[v]; 28 | return p[u]; } 29 | int kth(int u, int k) { 30 | if (k > d[u]) return -1; 31 | k = d[u] - k; 32 | while (d[u] > k) u = d[j[u]] >= k ? j[u] : p[u]; 33 | return u; } }; 34 | -------------------------------------------------------------------------------- /content/math/FracBinarySearch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Lucian Bicsi, Simon Lindholm 3 | * Date: 2017-10-31 4 | * License: CC0 5 | * Description: Given $f$ and $N$, finds the smallest fraction $p/q \in [0, 1]$ 6 | * such that $f(p/q)$ is true, and $p, q \le N$. 7 | * You may want to throw an exception from $f$ if it finds an exact solution, 8 | * in which case $N$ can be removed. 9 | * Usage: fracBS([](Frac f) { return f.p>=3*f.q; }, 10); // {1,3} 10 | * Time: O(\log(N)) 11 | * Status: stress-tested for n <= 300 12 | */ 13 | struct Frac { ll p, q; }; 14 | template Frac fracBS(F f, ll N) { 15 | bool dir = 1, A = 1, B = 1; 16 | Frac lo{0, 1}, hi{1, 1}; // Set hi to 1/0 to search (0, N] 17 | if (f(lo)) return lo; 18 | assert(f(hi)); 19 | while (A || B) { 20 | ll adv = 0, step = 1; // move hi if dir, else lo 21 | for (int si = 0; step; (step *= 2) >>= si) { 22 | adv += step; 23 | Frac mid{lo.p * adv + hi.p, lo.q * adv + hi.q}; 24 | if (abs(mid.p) > N || mid.q > N || dir == !f(mid)) { 25 | adv -= step; 26 | si = 2; } } 27 | hi.p += lo.p * adv; 28 | hi.q += lo.q * adv; 29 | dir = !dir; 30 | swap(lo, hi); 31 | A = B; 32 | B = !!adv; } 33 | return dir ? hi : lo; } 34 | -------------------------------------------------------------------------------- /tests/graphs/SCCKosaraju.cpp: -------------------------------------------------------------------------------- 1 | // Tested on https://codeforces.com/problemset/problem/427/C 2 | 3 | #include 4 | using namespace std; 5 | 6 | using ll = long long; 7 | 8 | #include "../../content/graphs/SCCKosaraju.h" 9 | 10 | int main() { 11 | cin.tie(0)->sync_with_stdio(0); 12 | cin.exceptions(cin.failbit); 13 | 14 | const ll MOD = 1000000007; 15 | 16 | int n; 17 | cin >> n; 18 | 19 | vector cost(n); 20 | for (int& x : cost) cin >> x; 21 | 22 | vector> adj(n); 23 | int m; 24 | cin >> m; 25 | 26 | for (int i = 0; i < m; i++) { 27 | int u, v; 28 | cin >> u >> v; 29 | adj[u - 1].push_back(v - 1); 30 | } 31 | 32 | vector comp = SCCKosaraju::scc(adj); 33 | vector add(comp.size(), (int)1e9 + 10); 34 | vector cnt(comp.size(), 1); 35 | int ncomps = 0; 36 | 37 | for (int i = 0; i < n; i++) { 38 | ncomps = max(ncomps, comp[i] + 1); 39 | 40 | if (cost[i] < add[comp[i]]) { 41 | add[comp[i]] = cost[i]; 42 | cnt[comp[i]] = 1; 43 | } else if (cost[i] == add[comp[i]]) 44 | cnt[comp[i]]++; 45 | } 46 | 47 | ll ans = 0, ways = 1; 48 | for (int i = 0; i < ncomps; i++) ans += add[i]; 49 | for (int i = 0; i < ncomps; i++) ways = (ways * cnt[i]) % MOD; 50 | 51 | cout << ans << " " << ways << '\n'; 52 | } 53 | -------------------------------------------------------------------------------- /content/number-theory/ModSqrt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2016-08-31 4 | * License: CC0 5 | * Source: http://eli.thegreenplace.net/2009/03/07/computing-modular-square-roots-in-python/ 6 | * Description: Tonelli-Shanks algorithm for modular square roots. Finds $x$ s.t. $x^2 = a \pmod p$ ($-x$ gives the other solution). 7 | * Time: O(\log^2 p) worst case, O(\log p) for most $p$ 8 | * Status: Tested for all a,p <= 10000 9 | */ 10 | #pragma once 11 | #include "ModPow.h" 12 | ll sqrt(ll a, ll p) { 13 | a %= p; 14 | if (a < 0) a += p; 15 | if (a == 0) return 0; 16 | assert(modpow(a, (p - 1) / 2, p) == 1); // else no solution 17 | if (p % 4 == 3) return modpow(a, (p + 1) / 4, p); 18 | // a^(n+3)/8 or 2^(n+3)/8 * 2^(n-1)/4 works if p % 8 == 5 19 | ll s = p - 1, n = 2; 20 | int r = 0, m; 21 | while (s % 2 == 0) ++r, s /= 2; /// find a non-square mod p 22 | while (modpow(n, (p - 1) / 2, p) != p - 1) ++n; 23 | ll x = modpow(a, (s + 1) / 2, p); 24 | ll b = modpow(a, s, p), g = modpow(n, s, p); 25 | for (; ; r = m) { 26 | ll t = b; 27 | for (m = 0; m < r && t != 1; ++m) t = t * t % p; 28 | if (m == 0) return x; 29 | ll gs = modpow(g, 1LL << (r - m - 1), p); 30 | g = gs * gs % p; 31 | x = x * gs % p; 32 | b = b * g % p; } } 33 | -------------------------------------------------------------------------------- /content/number-theory/ModMulLL.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: chilli, Ramchandra Apte, Noam527, Simon Lindholm 3 | * Date: 2019-04-24 4 | * License: CC0 5 | * Source: https://github.com/RamchandraApte/OmniTemplate/blob/master/modulo.hpp 6 | * Description: Calculate $a\cdot b\bmod c$ (or $a^b \bmod c$) for $0 \le a, b \le c \le 7.2\cdot 10^{18}$. 7 | * Time: O(1) for \texttt{modmul}, O(\log b) for \texttt{modpow} 8 | * Status: stress-tested, proven correct 9 | * Details: 10 | * This runs ~2x faster than the naive (__int128_t)a * b % M. 11 | * A proof of correctness is in doc/modmul-proof.tex. An earlier version of the proof, 12 | * from when the code used a * b / (long double)M, is in doc/modmul-proof.md. 13 | * The proof assumes that long doubles are implemented as x87 80-bit floats; if they 14 | * are 64-bit, as on e.g. MSVC, the implementation is only valid for 15 | * $0 \le a, b \le c < 2^{52} \approx 4.5 \cdot 10^{15}$. 16 | */ 17 | #pragma once 18 | typedef unsigned long long ull; 19 | ull modmul(ull a, ull b, ull M) { 20 | ll ret = a * b - M * ull(1.L / M * a * b); 21 | return ret + M * (ret < 0) - M * (ret >= (ll)M); } 22 | ull modpow(ull b, ull e, ull mod) { 23 | ull ans = 1; 24 | for (; e; b = modmul(b, b, mod), e /= 2) if (e & 1) 25 | ans = modmul(ans, b, mod); 26 | return ans; } 27 | -------------------------------------------------------------------------------- /content/graphs/GomoryHu.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: chilli, Takanori MAEHARA 3 | * Date: 2020-04-03 4 | * License: CC0 5 | * Source: https://github.com/spaghetti-source/algorithm/blob/master/graph/gomory_hu_tree.cc#L102 6 | * Description: Given a list of edges representing an undirected flow graph, 7 | * returns edges of the Gomory-Hu tree. The max flow between any pair of 8 | * vertices is given by minimum edge weight along the Gomory-Hu tree path. 9 | * Time: $O(V)$ Flow Computations 10 | * Status: Tested on CERC 2015 J, stress-tested 11 | * 12 | * Details: The implementation used here is not actually the original 13 | * Gomory-Hu, but Gusfield's simplified version: "Very simple methods for all 14 | * pairs network flow analysis". PushRelabel is used here, but any flow 15 | * implementation that supports `leftOfMinCut` also works. 16 | */ 17 | #pragma once 18 | #include "PushRelabel.h" 19 | typedef array Edge; 20 | vector gomoryHu(int N, vector ed) { 21 | vector tree; 22 | vi par(N); 23 | rep (i, 1, N) { 24 | PushRelabel D(N); // Dinic also works 25 | for (Edge t : ed) D.addEdge(t[0], t[1], t[2], t[2]); 26 | tree.push_back({i, par[i], D.calc(i, par[i])}); 27 | rep (j, i + 1, N) 28 | if (par[j] == par[i] && D.leftOfMinCut(j)) par[j] = i; } 29 | return tree; } 30 | -------------------------------------------------------------------------------- /content/number-theory/BerlekampMassey.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Lucian Bicsi 3 | * Date: 2017-10-31 4 | * License: CC0 5 | * Source: Wikipedia 6 | * Description: Recovers any $n$-order linear recurrence relation from the first 7 | * $2n$ terms of the recurrence. 8 | * Useful for guessing linear recurrences after brute-forcing the first terms. 9 | * Should work on any field, but numerical stability for floats is not guaranteed. 10 | * Output will have size $\le n$. 11 | * Usage: berlekampMassey({0, 1, 1, 3, 5, 11}) // {1, 2} 12 | * Time: O(N^2) 13 | * Status: bruteforce-tested mod 5 for n <= 5 and all s 14 | */ 15 | #pragma once 16 | #include "../number-theory/ModPow.h" 17 | vector berlekampMassey(vector s) { 18 | int n = sz(s), L = 0, m = 0; 19 | vector C(n), B(n), T; 20 | C[0] = B[0] = 1; 21 | ll b = 1; 22 | rep (i, 0, n) { 23 | ++m; 24 | ll d = s[i] % mod; 25 | rep (j, 1, L + 1) d = (d + C[j] * s[i - j]) % mod; 26 | if (!d) continue; 27 | T = C; 28 | ll coef = d * modpow(b, mod - 2) % mod; 29 | rep (j, m, n) C[j] = (C[j] - coef * B[j - m]) % mod; 30 | if (2 * L > i) continue; 31 | L = i + 1 - L; 32 | B = T; 33 | b = d; 34 | m = 0; } 35 | C.resize(L + 1); 36 | C.erase(C.begin()); 37 | for (ll& x : C) x = (mod - x) % mod; 38 | return C; } 39 | -------------------------------------------------------------------------------- /content/number-theory/LinearRecurrence.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Lucian Bicsi 3 | * Date: 2018-02-14 4 | * License: CC0 5 | * Source: Chinese material 6 | * Description: Generates the $k$'th term of an $n$-order 7 | * linear recurrence $S[i] = \sum_j S[i-j-1]tr[j]$, 8 | * given $S[0 \ldots \ge n-1]$ and $tr[0 \ldots n-1]$. 9 | * Faster than matrix multiplication. 10 | * Useful together with Berlekamp--Massey. 11 | * Usage: linearRec({0, 1}, {1, 1}, k) // k'th Fibonacci number 12 | * Time: O(n^2 \log k) 13 | * Status: bruteforce-tested mod 5 for n <= 5 14 | */ 15 | #pragma once 16 | const ll mod = 5; 17 | /** exclude-line */ 18 | typedef vector Poly; 19 | ll linearRec(Poly S, Poly tr, ll k) { 20 | int n = sz(tr); 21 | auto combine = [&](Poly a, Poly b) { 22 | Poly res(n * 2 + 1); 23 | rep (i, 0, n + 1) rep (j, 0, n + 1) 24 | res[i + j] = (res[i + j] + a[i] * b[j]) % mod; 25 | for (int i = 2 * n; i > n; --i) rep (j, 0, n) 26 | res[i - 1 - j] = (res[i - 1 - j] + res[i] * tr[j]) % mod; 27 | res.resize(n + 1); 28 | return res; }; 29 | Poly pol(n + 1), e(pol); 30 | pol[0] = e[1] = 1; 31 | for (++k; k; k /= 2) { 32 | if (k % 2) pol = combine(pol, e); 33 | e = combine(e, e); } 34 | ll res = 0; 35 | rep (i, 0, n) res = (res + pol[i + 1] * S[i]) % mod; 36 | return res; } 37 | -------------------------------------------------------------------------------- /content/data-structures/LinkCutTree.h: -------------------------------------------------------------------------------- 1 | struct LinkCut : SplayTree { 2 | // https://codeforces.com/blog/entry/75885 3 | LinkCut(int n): SplayTree(n) {} 4 | int access(int x) { 5 | int u = x, v = 0; 6 | for (; u; v = u, u = T[u].p) { 7 | splay(u); 8 | int& ov = T[u].ch[1]; 9 | T[u].vir += T[ov].sub; 10 | T[u].vir -= T[v].sub; 11 | ov = v; 12 | pull(u); } 13 | return splay(x), v; } 14 | void reroot(int x) { access(x); T[x].flip ^= 1; push(x); } 15 | void Link(int u, int v) { 16 | reroot(u), access(v); 17 | T[v].vir += T[u].sub; 18 | T[u].p = v; 19 | pull(v); } 20 | void Cut(int u, int v) { 21 | reroot(u), access(v); 22 | T[v].ch[0] = T[u].p = 0; 23 | pull(v); } 24 | // Rooted tree LCA. Returns 0 if u and v arent connected. 25 | int LCA(int u, int v) { 26 | if (u == v) return u; 27 | access(u); 28 | int ret = access(v); 29 | return T[u].p ? ret : 0; } 30 | // Query subtree of u where v is outside the subtree. 31 | ll Subtree(int u, int v) { 32 | reroot(v), access(u); 33 | return T[u].vir + T[u].self; } // Query path [u..v] 34 | ll Path(int u, int v) { 35 | reroot(u), access(v); 36 | return T[v].path; } // Update vertex u with value v 37 | void Update(int u, 38 | ll v) { access(u); T[u].self = v; pull(u); } }; 39 | -------------------------------------------------------------------------------- /content/numerical/GoldenSectionSearch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-04-17 4 | * License: CC0 5 | * Source: Numeriska algoritmer med matlab, Gerd Eriksson, NADA, KTH 6 | * Description: Finds the argument minimizing the function $f$ in the interval $[a,b]$ assuming $f$ is unimodal on the interval, i.e. has only one local minimum. The maximum error in the result is $eps$. Works equally well for maximization with a small change in the code. See TernarySearch.h in the Various chapter for a discrete version. 7 | * Usage: 8 | double func(double x) { return 4+x+.3*x*x; } 9 | double xmin = gss(-1000,1000,func); 10 | * Time: O(\log((b-a) / \epsilon)) 11 | * Status: tested 12 | */ 13 | #pragma once 14 | /// It is important for r to be precise, otherwise we don't necessarily maintain the inequality a < x1 < x2 < b. 15 | double gss(double a, double b, double (*f)(double)) { 16 | double r = (sqrt(5) - 1) / 2, eps = 1e-7; 17 | double x1 = b - r * (b - a), x2 = a + r * (b - a); 18 | double f1 = f(x1), f2 = f(x2); 19 | while (b - a > eps) 20 | if (f1 < f2) { //change to > to find maximum 21 | b = x2; 22 | x2 = x1; 23 | f2 = f1; 24 | x1 = b - r * (b - a); 25 | f1 = f(x1); 26 | } else { 27 | a = x1; 28 | x1 = x2; 29 | f1 = f2; 30 | x2 = a + r * (b - a); 31 | f2 = f(x2); 32 | } 33 | return a; 34 | } 35 | -------------------------------------------------------------------------------- /content/crackpack/VecL.java: -------------------------------------------------------------------------------- 1 | 2 | class VecL implements Comparable { 3 | long x, y; 4 | public VecL(long x, long y) {this.x=x;this.y=y;} 5 | public VecL add(VecL o) {return new VecL(x+o.x, y+o.y);} 6 | public VecL sub(VecL o) {return new VecL(x-o.x, y-o.y);} 7 | public VecL scale(long s) {return new VecL(x*s, y*s);} 8 | public long dot(VecL o) {return x*o.x+y*o.y;} 9 | public long cross(VecL o) {return x*o.y-y*o.x;} 10 | public long mag2() {return dot(this);} 11 | public VecL rot90() {return new VecL(-y, x);} 12 | public VecL rot270() {return new VecL(y, -x);} 13 | public String toString() {return "("+x+", "+y+")";} 14 | public int hashCode() {return Long.hashCode(x<<13^(y*57));} 15 | 16 | public boolean equals(Object oo) { 17 | VecL o=(VecL)oo; 18 | return x==o.x&&y==o.y; 19 | } 20 | 21 | public int compareTo(VecL o) { 22 | if (x!=o.x) return Long.compare(x, o.x); 23 | return Long.compare(y, o.y); 24 | } 25 | 26 | //origin->q1, axes-> quadrant in ccw direction 27 | public int quadrant() { 28 | if (x==0||y==0) 29 | if (y==0) return x>=0 ? 1 : 3; 30 | else return y>=0 ? 2 : 4; 31 | if (x>0) return y>0 ? 1 : 4; 32 | else return y>0 ? 2 : 3; 33 | } 34 | 35 | public int radialCompare(VecL o) { 36 | if (quadrant()==o.quadrant()) 37 | return -Long.signum(cross(o)); 38 | return Integer.compare(quadrant(), o.quadrant()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /content/geometry/lineIntersection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Victor Lecomte, chilli 3 | * Date: 2019-05-05 4 | * License: CC0 5 | * Source: https://vlecomte.github.io/cp-geo.pdf 6 | * Description:\\ 7 | \begin{minipage}{75mm} 8 | If a unique intersection point of the lines going through s1,e1 and s2,e2 exists \{1, point\} is returned. 9 | If no intersection point exists \{0, (0,0)\} is returned and if infinitely many exists \{-1, (0,0)\} is returned. 10 | The wrong position will be returned if P is Point and the intersection point does not have integer coordinates. 11 | Products of three coordinates are used in intermediate steps so watch out for overflow if using int or ll. 12 | \end{minipage} 13 | \begin{minipage}{15mm} 14 | \includegraphics[width=\textwidth]{content/geometry/lineIntersection} 15 | \end{minipage} 16 | * Usage: 17 | * auto res = lineInter(s1,e1,s2,e2); 18 | * if (res.first == 1) 19 | * cout << "intersection point at " << res.second << endl; 20 | * Status: stress-tested, and tested through half-plane tests 21 | */ 22 | #pragma once 23 | #include "Point.h" 24 | template 25 | pair lineInter(P s1, P e1, P s2, P e2) { 26 | auto d = (e1 - s1).cross(e2 - s2); 27 | if (d == 0) // if parallel 28 | return {-(s1.cross(e1, s2) == 0), P(0, 0)}; 29 | auto p = s2.cross(e1, e2), q = s2.cross(e2, s1); 30 | return {1, (s1 * p + e1 * q) / d}; } 31 | -------------------------------------------------------------------------------- /content/graphs/SCCTarjan.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Finds strongly connected components of a 3 | * directed graph. Visits/indexes SCCs in reverse topological 4 | * order. 5 | * Time: $O(|V| + |E|)$ 6 | * Usage: scc(graph) returns an array that has the ID of each 7 | * node's SCC. scc(graph, [\&](vector\& v) { ... }) calls 8 | * the lambda on each SCC, and returns the same array. 9 | * Multiple edges are not allowed. 10 | */ 11 | namespace SCCTarjan { 12 | vector val, comp, z, cont; 13 | int Time, ncomps; 14 | template int dfs(int j, G& g, F& f) { 15 | int low = val[j] = ++Time, x; 16 | z.push_back(j); 17 | for (auto e : g[j]) 18 | if (comp[e] < 0) low = min(low, val[e] ?: dfs(e, g, f)); 19 | if (low == val[j]) { 20 | do { 21 | x = z.back(); 22 | z.pop_back(); 23 | comp[x] = ncomps; 24 | cont.push_back(x); 25 | } while (x != j); 26 | f(cont); 27 | cont.clear(); 28 | ncomps++; 29 | } 30 | return val[j] = low; 31 | } 32 | template vector scc(G& g, F f) { 33 | int n = g.size(); 34 | val.assign(n, 0); 35 | comp.assign(n, -1); 36 | Time = ncomps = 0; 37 | for (int i = 0; i < n; i++) 38 | if (comp[i] < 0) dfs(i, g, f); 39 | return comp; 40 | } 41 | template // convenience function w/o lambda 42 | vector scc(G& g) { 43 | return scc(g, [](auto& v) {}); 44 | } 45 | } // namespace SCCTarjan 46 | -------------------------------------------------------------------------------- /content/geometry/ManhattanMST.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: chilli, Takanori MAEHARA 3 | * Date: 2019-11-02 4 | * License: CC0 5 | * Source: https://github.com/spaghetti-source/algorithm/blob/master/geometry/rectilinear_mst.cc 6 | * Description: Given N points, returns up to 4*N edges, which are guaranteed 7 | * to contain a minimum spanning tree for the graph with edge weights w(p, q) = 8 | * |p.x - q.x| + |p.y - q.y|. Edges are in the form (distance, src, dst). Use a 9 | * standard MST algorithm on the result to find the final MST. 10 | * Time: O(N \log N) 11 | * Status: Stress-tested 12 | */ 13 | #pragma once 14 | #include "Point.h" 15 | typedef Point P; 16 | vector> manhattanMST(vector

ps) { 17 | vi id(sz(ps)); 18 | iota(all(id), 0); 19 | vector> edges; 20 | rep (k, 0, 4) { 21 | sort(all(id), [&](int i, int j) { 22 | return (ps[i] - ps[j]).x < (ps[j] - ps[i]).y; }); 23 | map sweep; 24 | for (int i : id) { 25 | for (auto it = sweep.lower_bound(-ps[i].y); 26 | it != sweep.end(); 27 | sweep.erase(it++)) { 28 | int j = it->second; 29 | P d = ps[i] - ps[j]; 30 | if (d.y > d.x) break; 31 | edges.push_back({d.y + d.x, i, j}); } 32 | sweep[-ps[i].y] = i; } 33 | for (P& p : ps) if (k & 1) p.x = -p.x; 34 | else swap(p.x, p.y); } 35 | return edges; } 36 | -------------------------------------------------------------------------------- /content/test-session/chapter.tex: -------------------------------------------------------------------------------- 1 | \appendix 2 | \chapter{Test session} 3 | 4 | \section{To test during test session} 5 | \begin{itemize} 6 | \item Keyboard layouts 7 | \item bashrc 8 | \item vimrc 9 | \item template.cpp 10 | \item Java 11 | \item Python 12 | \item Printing 13 | \item Sending clarifications 14 | \item Documentation 15 | \item Submit script 16 | \item Whitespace/case insensitivity in output 17 | \item Return values from main 18 | \item Printing to stderr 19 | \item Source code limit 20 | \item Is it possible to submit and read from non-source files? 21 | \item SIMD support on machine resp. judge 22 | \item How long do array accesses take on machine resp. judge? 23 | \item How long do small operations take on machine resp. judge? 24 | \item Does \texttt{clock()} work? 25 | \item All judge errors: 26 | \begin{itemize} 27 | \item Accepted 28 | \item WA 29 | \item Presentation Error 30 | \item RTE (what results in RTE?) 31 | \item TLE 32 | \item Memory limit, both stack and heap 33 | \item Output limit 34 | \item Illegal function 35 | \item Compile error 36 | \item Compile time limit exceeded 37 | \item Compile memory limit exceeded 38 | \item Too late 39 | \end{itemize} 40 | \item Listing all available binaries\\ 41 | \texttt{echo \$PATH | tr ':' ' ' | xargs ls | grep -v / | sort | uniq | tr '\char`\\n' ' ' > path.txt} 42 | \end{itemize} 43 | -------------------------------------------------------------------------------- /content/strings/ahocorasick.h: -------------------------------------------------------------------------------- 1 | const int ALPHA = 26; 2 | struct AhoCorasick { 3 | int nodeCount; 4 | vector> transition, children; 5 | vector term, leaf; 6 | queue q; 7 | AhoCorasick() {} 8 | AhoCorasick(vector& strs) { 9 | int maxNodes = 1; 10 | for (string& s : strs) maxNodes += (int)s.length(); 11 | transition.resize(ALPHA); 12 | children.resize(ALPHA, vector(maxNodes)); 13 | leaf.resize(maxNodes); 14 | nodeCount = 1; 15 | for (string& s : strs) { 16 | int node = 0; 17 | for (char& ch : s) { 18 | int c = ch - 'a'; 19 | if (children[c][node] == 0) 20 | children[c][node] = nodeCount++; 21 | node = children[c][node]; } 22 | leaf[node]++; } 23 | for (int i = 0; i < ALPHA; ++i) 24 | transition[i].resize(nodeCount); 25 | term.resize(nodeCount); 26 | q.push(0), q.push(0); 27 | while (q.size()) { 28 | int node = q.front(); 29 | q.pop(); 30 | int suffLink = q.front(); 31 | q.pop(); 32 | term[node] = leaf[node] + term[suffLink]; 33 | for (int ch = 0; ch < ALPHA; ++ch) { 34 | if (children[ch][node] != 0) { 35 | transition[ch][node] = children[ch][node]; 36 | q.push(children[ch][node]); 37 | q.push(node == 0 ? 0 : transition[ch][suffLink]); } 38 | else { 39 | transition[ch][node] = transition[ch][suffLink]; } } 40 | } } }; 41 | -------------------------------------------------------------------------------- /content/graphs/TwoEdgeCCs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Finds all Two Edge Connected Components and 3 | * constructs a meta graph. The meta tree constructed has all 4 | * nodes of the same 2ECC compressed into one, with bridges 5 | * connecting them. Multi-edges are NOT bridges. 6 | * Time: O(V + E) 7 | */ 8 | vector> ed; 9 | int preCnt, metaN, stkSz; 10 | vi pre, metaMap, stk; 11 | void pop(int stop) { 12 | while (stkSz > 0) { 13 | int curr = stk[--stkSz]; 14 | metaMap[curr] = metaN; 15 | if (curr == stop) break; } 16 | ++metaN; } 17 | int dfs(int idx, int par) { 18 | int low = pre[idx] = ++preCnt; 19 | stk[stkSz++] = idx; 20 | for (auto [v, id] : ed[idx]) { 21 | if (id == par) continue; 22 | if (pre[v] != -1) low = min(low, pre[v]); // back edge 23 | else { 24 | int get = dfs(v, id); 25 | low = min(low, get); 26 | if (get == pre[v]) pop(v); // bridge 27 | } } 28 | if (par == -1 && stkSz) pop(idx); // root case 29 | return low; } 30 | vector> getMeta() { 31 | int n = sz(ed); 32 | preCnt = -1; 33 | metaN = 0; 34 | pre.assign(n, -1); 35 | metaMap.resize(n); 36 | stk.resize(n); 37 | stkSz = 0; 38 | rep (i, 0, n) if (pre[i] == -1) dfs(i, -1); 39 | vector> metaEdges(metaN); 40 | rep (u, 0, n) for (auto [v, id] : ed[u]) 41 | if (metaMap[u] != metaMap[v]) 42 | metaEdges[metaMap[u]].emplace_back(metaMap[v], id); 43 | return metaEdges; } 44 | -------------------------------------------------------------------------------- /content/data-structures/LineContainer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2017-04-20 4 | * License: CC0 5 | * Source: own work 6 | * Description: Container where you can add lines of the form kx+m, and query maximum values at points x. 7 | * Useful for dynamic programming (``convex hull trick''). 8 | * Time: O(\log N) 9 | * Status: stress-tested 10 | */ 11 | #pragma once 12 | struct Line { 13 | mutable ll k, m, p; 14 | bool operator<(const Line& o) const { return k < o.k; } 15 | bool operator<(ll x) const { return p < x; } }; 16 | struct LineContainer : multiset> { 17 | // (for doubles, use inf = 1/.0, div(a,b) = a/b) 18 | static const ll inf = LLONG_MAX; 19 | ll div(ll a, ll b) { // floored division 20 | return a / b - ((a ^ b) < 0 && a % b); } 21 | bool isect(iterator x, iterator y) { 22 | if (y == end()) return x->p = inf, 0; 23 | if (x->k == y->k) x->p = x->m > y->m ? inf : -inf; 24 | else x->p = div(y->m - x->m, x->k - y->k); 25 | return x->p >= y->p; } 26 | void add(ll k, ll m) { // for min, k *= -1, m *= -1; 27 | auto z = insert({k, m, 0}), y = z++, x = y; 28 | while (isect(y, z)) z = erase(z); 29 | if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); 30 | while ((y = x) != begin() && (--x)->p >= y->p) 31 | isect(x, erase(y)); } 32 | ll query(ll x) { 33 | assert(!empty()); 34 | auto l = *lower_bound(x); 35 | return l.k * x + l.m; // for min, -(l.k * x + l.m) 36 | } }; 37 | -------------------------------------------------------------------------------- /content/numerical/SolveLinear.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Per Austrin, Simon Lindholm 3 | * Date: 2004-02-08 4 | * License: CC0 5 | * Description: Solves $A * x = b$. If there are multiple solutions, an arbitrary one is returned. 6 | * Returns rank, or -1 if no solutions. Data in $A$ and $b$ is lost. 7 | * Time: O(n^2 m) 8 | * Status: tested on kattis:equationsolver, and bruteforce-tested mod 3 and 5 for n,m <= 3 9 | */ 10 | #pragma once 11 | typedef vector vd; 12 | const double eps = 1e-12; 13 | int solveLinear(vector& A, vd& b, vd& x) { 14 | int n = sz(A), m = sz(x), rank = 0, br, bc; 15 | if (n) assert(sz(A[0]) == m); 16 | vi col(m); 17 | iota(all(col), 0); 18 | rep (i, 0, n) { 19 | double v, bv = 0; 20 | rep (r, i, n) rep (c, i, m) if ((v = fabs(A[r][c])) > bv) 21 | br = r, bc = c, bv = v; 22 | if (bv <= eps) { 23 | rep (j, i, n) if (fabs(b[j]) > eps) return -1; 24 | break; } 25 | swap(A[i], A[br]); 26 | swap(b[i], b[br]); 27 | swap(col[i], col[bc]); 28 | rep (j, 0, n) swap(A[j][i], A[j][bc]); 29 | bv = 1 / A[i][i]; 30 | rep (j, i + 1, n) { 31 | double fac = A[j][i] * bv; 32 | b[j] -= fac * b[i]; 33 | rep (k, i + 1, m) A[j][k] -= fac * A[i][k]; } 34 | rank++; } 35 | x.assign(m, 0); 36 | for (int i = rank; i--; ) { 37 | b[i] /= A[i][i]; 38 | x[col[i]] = b[i]; 39 | rep (j, 0, i) b[j] -= A[j][i] * b[i]; } 40 | return rank; // (multiple solutions if rank < m) 41 | } 42 | -------------------------------------------------------------------------------- /content/crackpack/LCA.java: -------------------------------------------------------------------------------- 1 | class Graph { 2 | int n, d, depth[], lift[][]; 3 | List[] adj; 4 | public Graph(int nn) { 5 | adj = new ArrayList[n = nn]; 6 | for(int i = 0 ; i < n ; i++) 7 | adj[i] = new ArrayList<>(); 8 | depth = new int[n]; 9 | d = Integer.numberOfTrailingZeros(Integer.highestOneBit(n)) + 2; 10 | lift = new int[d][n]; 11 | for(int i = 0 ; i < d ; i++) Arrays.fill(lift[i], -1); 12 | } 13 | void add(int u, int v) { adj[u].add(v); adj[v].add(u); } 14 | void build() { 15 | Deque q = new ArrayDeque<>(); 16 | q.add(0); 17 | while(!q.isEmpty()) { 18 | int u = q.pop(); 19 | for(int v : adj[u]) { 20 | if(lift[0][u] != v) { 21 | lift[0][v] = u; 22 | depth[v] = depth[u] + 1; 23 | q.add(v); 24 | } 25 | } 26 | } 27 | for(int k = 0 ; k < d - 1 ; k++) 28 | for(int i = 0 ; i < n ; i++) 29 | if(lift[k][i] != -1) 30 | lift[k + 1][i] = lift[k][lift[k][i]]; 31 | } 32 | int lca(int u, int v) { 33 | if(depth[v] > depth[u]) return lca(v, u); 34 | u = walk(u, depth[u] - depth[v]); 35 | if(u == v) return u; 36 | for(int k = d - 1 ; k >= 0 ; k--) { 37 | if(lift[k][u] != lift[k][v]) { 38 | u = lift[k][u]; 39 | v = lift[k][v]; 40 | } 41 | } 42 | return lift[0][u]; 43 | } 44 | int walk(int u, int k) { 45 | for(int i = 0 ; i < d && u != -1 ; i++) if((k & (1 << i)) > 0) u = lift[i][u]; 46 | return u; 47 | } 48 | int dist(int u, int v) { return depth[u] + depth[v] - (2 * depth[lca(u, v)]); } 49 | } -------------------------------------------------------------------------------- /content/math/ContinuedFractions.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2018-07-15 4 | * License: CC0 5 | * Source: Wikipedia 6 | * Description: Given $N$ and a real number $x \ge 0$, finds the closest rational approximation $p/q$ with $p, q \le N$. 7 | * It will obey $|p/q - x| \le 1/qN$. 8 | * 9 | * For consecutive convergents, $p_{k+1}q_k - q_{k+1}p_k = (-1)^k$. 10 | * ($p_k/q_k$ alternates between $>x$ and $ approximate(d x, ll N) { 18 | ll LP = 0, LQ = 1, P = 1, Q = 0, inf = LLONG_MAX; 19 | d y = x; 20 | for (; ; ) { 21 | ll lim = min(P ? (N - LP) / P : inf, 22 | Q ? (N - LQ) / Q : inf), a = (ll)floor(y), 23 | b = min(a, lim), NP = b * P + LP, NQ = b * Q + LQ; 24 | if (a > b) { 25 | // If b > a/2, we have a semi-convergent that gives us a 26 | // better approximation; if b = a/2, we *may* have one. 27 | // Return {P, Q} here for a more canonical approximation. 28 | return (abs(x - (d)NP / (d)NQ) < abs(x - (d)P / (d)Q)) 29 | ? make_pair(NP, NQ) 30 | : make_pair(P, Q); } 31 | if (abs(y = 1 / (y - (d)a)) > 3 * N) return {NP, NQ}; 32 | LP = P; 33 | P = NP; 34 | LQ = Q; 35 | Q = NQ; } } 36 | -------------------------------------------------------------------------------- /content/crackpack/Vec.java: -------------------------------------------------------------------------------- 1 | class Vec { 2 | static final double EPS=1e-6; 3 | double x, y; 4 | public Vec(double x, double y) {this.x=x;this.y=y;} 5 | public Vec add(Vec o) {return new Vec(x+o.x, y+o.y);} 6 | public Vec sub(Vec o) {return new Vec(x-o.x, y-o.y);} 7 | public Vec scale(double s) {return new Vec(x*s, y*s);} 8 | public double dot(Vec o) {return x*o.x+y*o.y;} 9 | public double cross(Vec o) {return x*o.y-y*o.x;} 10 | public double mag2() {return dot(this);} 11 | public double mag() {return Math.sqrt(mag2());} 12 | public Vec unit() {return scale(1/mag());} 13 | public Vec rot90() {return new Vec(-y, x);} 14 | public Vec rot270() {return new Vec(y, -x);} 15 | 16 | public Vec rotate(double theta) { 17 | double PI=Math.PI; 18 | double newX=x*Math.cos(theta)+y*Math.cos(PI/2+theta); 19 | double newY=x*Math.sin(theta)+y*Math.sin(PI/2+theta); 20 | return new Vec(newX, newY); 21 | } 22 | 23 | //angle between 0 and 2PI 24 | public double angle() { 25 | return (Math.atan2(y, x)+2*Math.PI)%(2*Math.PI); 26 | } 27 | 28 | public String toString() { 29 | DecimalFormat df=new DecimalFormat("#.##"); 30 | return "("+df.format(x)+", "+df.format(y)+")"; 31 | } 32 | 33 | static boolean eq(double a, double b) {return Math.abs(a-b)b;} 36 | 37 | public boolean equals(Object oo) { 38 | Vec o=(Vec)oo; 39 | return eq(x, o.x)&&eq(y, o.y); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /content/graphs/TwoVertexCCs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2017-04-17 4 | * License: CC0 5 | * Source: folklore 6 | * Description: Finds all Two Vertex Connected Components and 7 | * runs a callback for the edges in each. Note that a node can 8 | * be in several components. An edge which is not in a component is a bridge, 9 | * i.e., not part of any cycle. 10 | * Usage: 11 | * int eid = 0; ed.resize(N); 12 | * for each edge (a,b) { 13 | * ed[a].emplace_back(b, eid); 14 | * ed[b].emplace_back(a, eid++); } 15 | * twoVCCs([\&](const vi\& edgeIDs) {...}); 16 | * Time: O(E + V) 17 | * Status: tested during MIPT ICPC Workshop 2017 18 | */ 19 | #pragma once 20 | vi num, st; 21 | vector> ed; 22 | int Time; 23 | template int dfs(int at, int par, F& f) { 24 | int me = num[at] = ++Time, e, y, top = me; 25 | for (auto pa : ed[at]) 26 | if (pa.second != par) { 27 | tie(y, e) = pa; 28 | if (num[y]) { 29 | top = min(top, num[y]); 30 | if (num[y] < me) st.push_back(e); 31 | } else { 32 | int si = sz(st); 33 | int up = dfs(y, e, f); 34 | top = min(top, up); 35 | if (up == me) { 36 | st.push_back(e); 37 | f(vi(st.begin() + si, st.end())); 38 | st.resize(si); 39 | } else if (up < me) st.push_back(e); 40 | else { /* e is a bridge */ } 41 | } 42 | } 43 | return top; 44 | } 45 | template void twoVCCs(F f) { 46 | num.assign(sz(ed), 0); 47 | rep(i, 0, sz(ed)) if (!num[i]) dfs(i, -1, f); 48 | } 49 | -------------------------------------------------------------------------------- /content/number-theory/PrimeSieveFast.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Prime sieve for generating all primes smaller 3 | * than LIM. 4 | * 5 | * Time: LIM=1e9 $\approx$ 1.5s 6 | * 7 | * Details: Despite its n log log n complexity, segmented sieve 8 | * is still faster than other options, including bitset sieves 9 | * and linear sieves. This is primarily due to its low memory 10 | * usage, which reduces cache misses. This implementation skips 11 | * even numbers. 12 | * 13 | * Benchmark can be found here: https://ideone.com/e7TbX4 14 | * 15 | * The line `for (int i=idx; i isPrime; 21 | vector primeSieve() { 22 | const int S = round(sqrt(LIM)), R = LIM / 2; 23 | vector pr = {2}, sieve(S + 1); 24 | pr.reserve(int(LIM / log(LIM) * 1.1)); 25 | vector> cp; 26 | for (int i = 3; i <= S; i += 2) if (!sieve[i]) { 27 | cp.push_back({i, i * i / 2}); 28 | for (int j = i * i; j <= S; j += 2 * i) sieve[j] = 1; } 29 | for (int L = 1; L <= R; L += S) { 30 | array block{}; 31 | for (auto& [p, idx] : cp) 32 | for (int i = idx; i < S + L; idx = (i += p)) 33 | block[i - L] = 1; 34 | for (int i = 0; i < min(S, R - L); i++) if (!block[i]) 35 | pr.push_back((L + i) * 2 + 1); } 36 | for (int i : pr) isPrime[i] = 1; 37 | return pr; } 38 | -------------------------------------------------------------------------------- /content/crackpack/JS.java: -------------------------------------------------------------------------------- 1 | class JS { 2 | public int BS = 1<<16; 3 | public char NC = (char)0; 4 | byte[] buf = new byte[BS]; 5 | int bId = 0, size = 0; 6 | char c = NC; 7 | double num = 1; 8 | BufferedInputStream in; 9 | 10 | public JS() { 11 | in = new BufferedInputStream(System.in, BS); 12 | } 13 | 14 | public JS(String s) throws FileNotFoundException { 15 | in = new BufferedInputStream(new FileInputStream(new File(s)), BS); 16 | } 17 | 18 | public char nextChar(){ 19 | while(bId==size) { 20 | try { 21 | size = in.read(buf); 22 | }catch(Exception e) { 23 | return NC; 24 | } 25 | if(size==-1)return NC; 26 | bId=0; 27 | } 28 | return (char)buf[bId++]; 29 | } 30 | 31 | public int nextInt() { 32 | return (int)nextLong(); 33 | } 34 | 35 | public long nextLong() { 36 | num=1; 37 | boolean neg = false; 38 | if(c==NC)c=nextChar(); 39 | for(;(c<'0' || c>'9'); c = nextChar()) { 40 | if(c=='-')neg=true; 41 | } 42 | long res = 0; 43 | for(; c>='0' && c <='9'; c=nextChar()) { 44 | res = (res<<3)+(res<<1)+c-'0'; 45 | num*=10; 46 | } 47 | return neg?-res:res; 48 | } 49 | 50 | public double nextDouble() { 51 | double cur = nextLong(); 52 | return c!='.' ? cur:cur+(cur < 0 ? -1*nextLong()/num : nextLong()/num); 53 | } 54 | 55 | public String next() { 56 | StringBuilder res = new StringBuilder(); 57 | while(c<=32)c=nextChar(); 58 | while(c>32) { 59 | res.append(c); 60 | c=nextChar(); 61 | } 62 | return res.toString(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /content/data-structures/LiChaoTree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | template 3 | struct LiChao { 4 | static constexpr T oo = numeric_limits::max(); 5 | struct node { F f; node *l = 0, *r = 0; }; 6 | ll tlo, thi; 7 | node* root = 0; 8 | LiChao(ll lo, ll hi): tlo(lo), thi(hi) {} 9 | T query(ll x, node* u, ll lo, ll hi) { 10 | if (!u) return oo; 11 | if (lo + 1 == hi) return eval(u->f, x); 12 | ll mid = lo + (hi - lo) / 2; 13 | auto res = x < mid ? query(x, u->l, lo, mid) 14 | : query(x, u->r, mid, hi); 15 | return min(eval(u->f, x), res); 16 | } 17 | T query(ll x) { return query(x, root, tlo, thi); } 18 | void update(ll a, ll b, F f, node*& u, ll lo, ll hi) { 19 | if (b <= lo || hi <= a) return; 20 | ll mid = lo + (hi - lo) / 2; 21 | if (a <= lo && hi <= b) { 22 | if (!u) { u = new node({f}); return; } 23 | bool cl = eval(f, lo) < eval(u->f, lo); 24 | bool cm = eval(f, mid) < eval(u->f, mid); 25 | if (cm) swap(u->f, f); 26 | if (lo + 1 == hi) return; 27 | if (cl != cm) update(a, b, f, u->l, lo, mid); 28 | else update(a, b, f, u->r, mid, hi); 29 | return; 30 | } 31 | if (!u) u = new node({big()}); 32 | update(a, b, f, u->l, lo, mid); 33 | update(a, b, f, u->r, mid, hi); 34 | } 35 | void update(ll a, ll b, F f) { return update(a, b, f, root, tlo, thi); } 36 | }; 37 | -------------------------------------------------------------------------------- /content/math/FractionOverflow.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Safer struct for representing 3 | * fractions/rationals. Comparison is 100\% overflow safe; 4 | * other ops are safer but can still overflow. All ops are 5 | * $O(\log N)$. 6 | */ 7 | template struct QO { 8 | T a, b; 9 | QO(T p, T q = 1) { 10 | T g = gcd(p, q); 11 | a = p / g; 12 | b = q / g; 13 | if (b < 0) a = -a, b = -b; } 14 | T gcd(T x, T y) const { return __gcd(x, y); } 15 | QO operator+(const QO& o) const { 16 | T g = gcd(b, o.b), bb = b / g, obb = o.b / g; 17 | return {a * obb + o.a * bb, b * obb}; } 18 | QO operator-(const QO& o) const { 19 | return *this + QO(-o.a, o.b); } 20 | QO operator*(const QO& o) const { 21 | T g1 = gcd(a, o.b), g2 = gcd(o.a, b); 22 | return {(a / g1) * (o.a / g2), (b / g2) * (o.b / g1)}; } 23 | QO operator/(const QO& o) const { 24 | return *this * QO(o.b, o.a); } 25 | QO recip() const { return {b, a}; } 26 | int signum() const { return (a > 0) - (a < 0); } 27 | static bool lessThan(T a, T b, T x, T y) { 28 | if (a / b != x / y) return a / b < x / y; 29 | if (x % y == 0) return false; 30 | if (a % b == 0) return true; 31 | return lessThan(y, x % y, b, a % b); } 32 | bool operator<(const QO& o) const { 33 | if (this->signum() != o.signum() || a == 0) 34 | return a < o.a; 35 | if (a < 0) return lessThan(abs(o.a), o.b, abs(a), b); 36 | else return lessThan(a, b, o.a, o.b); } 37 | friend ostream& operator<<(ostream& cout, const QO& o) { 38 | return cout << o.a << "/" << o.b; } }; 39 | -------------------------------------------------------------------------------- /content/geometry/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Geometry} 2 | 3 | \section{Geometric primitives} 4 | \kactlimport{Point.h} 5 | \kactlimport{lineDistance.h} 6 | \kactlimport{SegmentDistance.h} 7 | \kactlimport{SegmentIntersection.h} 8 | \kactlimport{lineIntersection.h} 9 | \kactlimport{sideOf.h} 10 | \kactlimport{OnSegment.h} 11 | \kactlimport{linearTransformation.h} 12 | \kactlimport{LineProjectionReflection.h} 13 | \kactlimport{Angle.h} 14 | \kactlimport{angleCmp.h} 15 | 16 | \section{Circles} 17 | \kactlimport{CircleIntersection.h} 18 | \kactlimport{CircleTangents.h} 19 | \kactlimport{CircleLine.h} 20 | \kactlimport{CirclePolygonIntersection.h} 21 | \kactlimport{circumcircle.h} 22 | \kactlimport{MinimumEnclosingCircle.h} 23 | 24 | \section{Polygons} 25 | \kactlimport{InsidePolygon.h} 26 | \kactlimport{PolygonArea.h} 27 | \kactlimport{PolygonCenter.h} 28 | \kactlimport{PolygonCut.h} 29 | \kactlimport{PolygonUnion.h} 30 | \kactlimport{ConvexHull.h} 31 | \kactlimport{HullDiameter.h} 32 | \kactlimport{PointInsideHull.h} 33 | \kactlimport{LineHullIntersection.h} 34 | \kactlimport{halfPlane.h} 35 | \kactlimport{mitlineIntersection.h} 36 | \kactlimport{PlanarFaceExtraction.h} 37 | 38 | 39 | \section{Misc. Point Set Problems} 40 | \kactlimport{ClosestPair.h} 41 | \kactlimport{ManhattanMST.h} 42 | % \kactlimport{kdTree.h} 43 | % \kactlimport{DelaunayTriangulation.h} 44 | \kactlimport{FastDelaunay.h} 45 | 46 | \section{3D} 47 | \kactlimport{PolyhedronVolume.h} 48 | \kactlimport{Point3D.h} 49 | \kactlimport{3dHull.h} 50 | \kactlimport{sphericalDistance.h} 51 | -------------------------------------------------------------------------------- /content/crackpack/Plane.java: -------------------------------------------------------------------------------- 1 | 2 | class Plane { 3 | //point on plane and unit normal vector, p2 and p3 are arbitrary other points on the plane 4 | Vec3 p, n, p2, p3; 5 | 6 | Vec3 planeXAxis, planeYAxis; 7 | static final Vec3 randPoint1=new Vec3(157.157, 123.123, 0.102), 8 | randPoint2=new Vec3(-14.14, 3.14159, 814.12); 9 | 10 | public Plane(Vec3 p, Vec3 n) { 11 | this.p=p; 12 | this.n=n=n.unit(); 13 | 14 | p2=projectToPlane(randPoint1); 15 | p3=projectToPlane(randPoint2); 16 | 17 | planeXAxis=p2.sub(p).unit(); 18 | Vec3 p3Dir=p3.sub(p); 19 | planeYAxis=p3Dir.sub(planeXAxis.scale(planeXAxis.dot(p3Dir))).unit(); 20 | } 21 | 22 | public Vec3 projectToPlane(Vec3 o) { 23 | Vec3 dir=o.sub(p); 24 | return o.sub(n.scale(n.dot(dir))); 25 | } 26 | 27 | public Vec getXY(Vec3 o) { 28 | o=o.sub(p); 29 | return new Vec(o.dot(planeXAxis), o.dot(planeYAxis)); 30 | } 31 | 32 | //line-plane intersection 33 | public Vec3 intersect(Seg3 line) { 34 | if (parallelToLine(line)) 35 | return null; 36 | double speedToPlane=-line.dir.dot(n); 37 | double timeToPlane=dist(line.from)/speedToPlane; 38 | return line.from.add(line.dir.scale(timeToPlane)); 39 | } 40 | 41 | //point to plane distance, negative if below plane 42 | public double dist(Vec3 o) { 43 | return n.dot(o.sub(p)); 44 | } 45 | 46 | //checks if the plane is parallel to the line 47 | public boolean parallelToLine(Seg3 line) { 48 | return Vec.eq(line.dir.dot(n), 0); 49 | } 50 | 51 | public String toString() { 52 | return "{p: "+p+", n: "+n+"}"; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /content/crackpack/TwoSat.java: -------------------------------------------------------------------------------- 1 | static class TwoSat { 2 | int n, n2; byte[] vals, cvals; SCC scc; 3 | 4 | public TwoSat(int nn) { n2 = 2 * (n = nn); scc = new SCC(n2); vals = new byte[n2];} 5 | 6 | // Example: (true, 0, false, 1) => 0 --> !1 7 | public void addImpl(boolean va, int a, boolean vb, int b) { 8 | a <<= 1; b <<= 1; if (!va) a++; if (!vb) b++; 9 | scc.add(a, b); scc.add(b ^ 1, a ^ 1); 10 | } 11 | 12 | //# Add (a NAND b) 13 | public void addNand(boolean va, int a, boolean vb, int b) { 14 | addImpl(va, a, !vb, b); 15 | }//$ 16 | 17 | //# Add (a OR b) 18 | public void addOr(boolean va, int a, boolean vb, int b) { 19 | addImpl(!va, a, vb, b); // ~a -> b 20 | }//$ 21 | 22 | //# Add (a XOR b) 23 | public void addXor(boolean va, int a, boolean vb, int b) { 24 | addImpl(!va, a, vb, b); // ~a -> b 25 | addImpl(va, a, !vb, b); // a -> ~b 26 | }//$ 27 | 28 | //# Forces a to have whatever value va is 29 | public void addForce(int a, boolean va) { 30 | addImpl(!va, a, va, a); 31 | }//$ 32 | 33 | // Returns the value of the variable v 34 | public boolean getVal(int v) { 35 | return vals[v << 1] == 1; 36 | } 37 | 38 | public boolean solve() { 39 | int map[] = scc.go(); 40 | for(int i = 0; i < n; i++) { 41 | if(map[2*i] == map[2*i+1]) return false; 42 | } 43 | for(int i = 0; i < n2; i++) vals[i] = (byte)-1; 44 | for(int i = 0; i < scc.cs; i++) { 45 | for(int v : scc.comp[i]) { 46 | if(vals[v] == -1) { 47 | vals[v] = 1; 48 | } 49 | vals[v^1] = (byte)(vals[v]^1); 50 | } 51 | } 52 | return true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /content/numerical/Multipoint.h: -------------------------------------------------------------------------------- 1 | vl inv(const vl& a, int N) { 2 | vl b = {modpow(a[0], mod - 2)}; 3 | int k = 1; 4 | for (int k = 2; k / 2 < N; k *= 2) { 5 | vl temp = {begin(a), sz(a) > k ? begin(a) + k : end(a)}; 6 | temp = conv(temp, b); 7 | for (int i = 0; i < sz(temp); i++) if (temp[i]) 8 | temp[i] = mod - temp[i]; 9 | temp[0] += 2; 10 | if (temp[0] >= mod) temp[0] -= mod; 11 | b = conv(temp, b); 12 | b.resize(min(k, N)); } 13 | return b; } 14 | pair div(vl& a, vl& b) { 15 | if (sz(a) < sz(b)) return {{}, a}; 16 | reverse(all(a)), reverse(all(b)); 17 | vl q = conv(a, inv(b, sz(a) - sz(b) + 1)); 18 | q.resize(sz(a) - sz(b) + 1); 19 | reverse(all(a)), reverse(all(b)), reverse(all(q)); 20 | int cap = 0; 21 | vl r = conv(b, q); 22 | rep (i, 0, sz(a)) { 23 | r[i] = a[i] + mod - r[i]; 24 | if (r[i] >= mod) r[i] -= mod; 25 | if (r[i]) cap = i + 1; } 26 | r.resize(cap); 27 | return {q, r}; } 28 | const int M = 1 << 17; 29 | vl t[4 * M]; // about 2 sec 30 | void build(int v, int lo, int hi, vl& x) { 31 | if (hi - lo == 1) // handle if negative or w/e 32 | t[v] = {x[lo] ? mod - x[lo] : 0, 1}; 33 | else { 34 | int mid = (lo + hi) / 2; 35 | build(2 * v, lo, mid, x), build(2 * v + 1, mid, hi, x); 36 | t[v] = conv(t[2 * v], t[2 * v + 1]); } } 37 | void calc(int v, int lo, int hi, vl a, vl& ans) { 38 | a = div(a, t[v]).second; 39 | if (hi - lo == 1) { ans[lo] = sz(a) ? a[0] : 0; return; } 40 | int mid = (lo + hi) / 2; 41 | calc(2 * v, lo, mid, a, ans); 42 | calc(2 * v + 1, mid, hi, a, ans); } 43 | -------------------------------------------------------------------------------- /content/crackpack/ConvexHull.java: -------------------------------------------------------------------------------- 1 | class ConvexHull { 2 | 3 | static VecL[] upperHull, lowerHull; 4 | 5 | public static VecL[] removeDupes(VecL[] points) { 6 | HashSet set=new HashSet<>(); 7 | for (VecL v:points) 8 | set.add(v); 9 | int counter=0; 10 | points=new VecL[set.size()]; 11 | for (VecL v:set) points[counter++]=v; 12 | return points; 13 | } 14 | 15 | // returns the hull in CCW order 16 | public static VecL[] getHull(VecL[] points) { 17 | points=points.clone(); 18 | Arrays.sort(points); 19 | if (points.length<3) 20 | return upperHull=lowerHull=points; 21 | int n=points.length, j=2, k=2; 22 | VecL[] lo=new VecL[n], up=new VecL[n]; 23 | lo[0]=points[0]; 24 | lo[1]=points[1]; 25 | for (int i=2; i1&&!right(lo[j-2], lo[j-1], p)) j--; 28 | lo[j++]=p; 29 | } 30 | up[0]=points[n-1]; 31 | up[1]=points[n-2]; 32 | for (int i=n-3; i>=0; i--) { 33 | VecL p=points[i]; 34 | while (k>1&&!right(up[k-2], up[k-1], p)) k--; 35 | up[k++]=p; 36 | } 37 | 38 | VecL[] res=new VecL[j+k-2]; 39 | for (int i=0; ib->c are in the right order 52 | static boolean right(VecL a, VecL b, VecL c) { 53 | return b.sub(a).cross(c.sub(a))>0; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /content/graphs/GeneralMatching.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2016-12-09 4 | * License: CC0 5 | * Source: http://www.mimuw.edu.pl/~mucha/pub/mucha_sankowski_focs04.pdf 6 | * Description: Matching for general graphs. 7 | * Fails with probability $N / mod$. 8 | * Time: O(N^3) 9 | * Status: not very well tested 10 | */ 11 | #pragma once 12 | #include "../numerical/MatrixInverse-mod.h" 13 | vector generalMatching(int N, vector& ed) { 14 | vector> mat(N, vector(N)), A; 15 | for (pii pa : ed) { 16 | int a = pa.first, b = pa.second, r = rand() % mod; 17 | mat[a][b] = r, mat[b][a] = (mod - r) % mod; 18 | } 19 | int r = matInv(A = mat), M = 2 * N - r, fi, fj; 20 | assert(r % 2 == 0); 21 | if (M != N) do { 22 | mat.resize(M, vector(M)); 23 | rep(i, 0, N) { 24 | mat[i].resize(M); 25 | rep(j, N, M) { 26 | int r = rand() % mod; 27 | mat[i][j] = r, mat[j][i] = (mod - r) % mod; 28 | } 29 | } 30 | } while (matInv(A = mat) != M); 31 | vi has(M, 1); 32 | vector ret; 33 | rep(it, 0, M / 2) { 34 | rep(i, 0, M) if (has[i]) 35 | rep(j, i + 1, M) if (A[i][j] && mat[i][j]) { 36 | fi = i; 37 | fj = j; 38 | goto done; 39 | } 40 | assert(0); 41 | done: 42 | if (fj < N) ret.emplace_back(fi, fj); 43 | has[fi] = has[fj] = 0; 44 | rep(sw, 0, 2) { 45 | ll a = modpow(A[fi][fj], mod - 2); 46 | rep(i, 0, M) if (has[i] && A[i][fj]) { 47 | ll b = A[i][fj] * a % mod; 48 | rep(j, 0, M) A[i][j] = (A[i][j] - A[fi][j] * b) % mod; 49 | } 50 | swap(fi, fj); 51 | } 52 | } 53 | return ret; 54 | } 55 | -------------------------------------------------------------------------------- /content/graphs/DominatorTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Given a digraph, return the edges of the dominator tree given as an adj. list (directed tree downwards from the root) 3 | * Time: $O((n + m) * log n)$ where n is the number of verticies in the graph and m is the number of edges 4 | * Status: Tested 5 | */ 6 | vector dominator_tree(const vector& adj, int root) { 7 | int n = sz(adj) + 1, co = 0; 8 | vector ans(n), radj(n), child(n), sdomChild(n); 9 | vi label(n), rlabel(n), sdom(n), dom(n), par(n), bes(n); 10 | auto get = [&](auto self, int x) -> int { 11 | if (par[x] != x) { 12 | int t = self(self, par[x]); 13 | par[x] = par[par[x]]; 14 | if (sdom[t] < sdom[bes[x]]) bes[x] = t; } 15 | return bes[x]; }; 16 | auto dfs = [&](auto self, int x) -> void { 17 | label[x] = ++co, rlabel[co] = x; 18 | sdom[co] = par[co] = bes[co] = co; 19 | for (auto y : adj[x]) { 20 | if (!label[y]) 21 | self(self, y), child[label[x]].push_back(label[y]); 22 | radj[label[y]].push_back(label[x]); } }; 23 | dfs(dfs, root); 24 | for (int i = co; i >= 1; --i) { 25 | for (auto j : radj[i]) 26 | sdom[i] = min(sdom[i], sdom[get(get, j)]); 27 | if (i > 1) sdomChild[sdom[i]].push_back(i); 28 | for (auto j : sdomChild[i]) { 29 | int k = get(get, j); 30 | if (sdom[j] == sdom[k]) dom[j] = sdom[j]; 31 | else dom[j] = k; } 32 | for (auto j : child[i]) par[j] = i; } 33 | for (int i = 2; i < co + 1; ++i) { 34 | if (dom[i] != sdom[i]) dom[i] = dom[dom[i]]; 35 | ans[rlabel[dom[i]]].push_back(rlabel[i]); } 36 | return ans; } 37 | -------------------------------------------------------------------------------- /content/graphs/Blossom.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: bicsi 3 | * Source: https://codeforces.com/blog/entry/92339?#comment-810242 4 | * Description: General matching in $O(nm)$. 5 | */ 6 | vi Blossom(vector& adj) { 7 | int n = adj.size(), T = -1; 8 | vi mate(n, -1), label(n), par(n), orig(n), aux(n, -1), q; 9 | auto lca = [&](int x, int y) { 10 | for (T++; ; swap(x, y)) { 11 | if (x == -1) continue; 12 | if (aux[x] == T) return x; 13 | aux[x] = T; 14 | x = (mate[x] == -1 ? -1 : orig[par[mate[x]]]); } }; 15 | auto blossom = [&](int v, int w, int a) { 16 | while (orig[v] != a) { 17 | par[v] = w; 18 | w = mate[v]; 19 | if (label[w] == 1) label[w] = 0, q.push_back(w); 20 | orig[v] = orig[w] = a, v = par[w]; } }; 21 | auto augment = [&](int v) { 22 | while (v != -1) { 23 | int pv = par[v], nv = mate[pv]; 24 | mate[v] = pv, mate[pv] = v, v = nv; } }; 25 | auto bfs = [&](int root) { 26 | fill(all(label), -1), iota(all(orig), 0); 27 | q.clear(), q.push_back(root), label[root] = 0; 28 | for (int i = 0; i < sz(q); i++) { 29 | int v = q[i]; 30 | for (auto x : adj[v]) if (label[x] == -1) { 31 | label[x] = 1, par[x] = v; 32 | if (mate[x] == -1) return augment(x); 33 | label[mate[x]] = 0, q.push_back(mate[x]); } 34 | else if (label[x] == 0 && orig[v] != orig[x]) { 35 | int a = lca(orig[v], orig[x]); 36 | blossom(x, v, a), blossom(v, x, a); } } }; 37 | // Time halves if you start with (any) maximal matching. 38 | for (int i = 0; i < n; i++) if (mate[i] == -1) bfs(i); 39 | return mate; } 40 | -------------------------------------------------------------------------------- /doc/example.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Chen Xing 3 | * Date: 2009-03-13 4 | * License: CC0 5 | * Source: Conversation with Håkan and Ulf. 6 | * Description: Example structures and functions that doesn't 7 | * really do anything. Latex commands are supported here, 8 | * though! Like this: $2^2=3$ Time: O(M * N^4) where M = cats, 9 | * N = mice Memory: O(2^N) where N = cats Status: Unknown 10 | * Usage: 11 | * int res = exampleFunction1(mice, cats, catsCount); 12 | * int random = exampleFunction2(); 13 | */ 14 | #pragma once 15 | /// Headers and macros from contest/template.h are 16 | /// automatically included. 17 | #include "Example.h" /// Header name will be kept in final list. 18 | struct ExampleStructure { 19 | ll alpha; 20 | pii nodes; 21 | vi edges; 22 | }; 23 | int exampleFunction1(vi mice, int* cats, int catsCount) { 24 | /// This is a stupid comment that will be removed. 25 | int sum = 0; 26 | rep(i, 1, catsCount) { 27 | // This comment will be kept! 28 | for (auto it : mice) { 29 | /// This will be removed. 30 | // And this kept. 31 | sum += cats[i] * it; 32 | } 33 | } 34 | // Use tab indent and keep a line width of at most 63 chars, 35 | // where tabs count as 2 characters wide. 36 | //<---------------------Maximum width-----------------------> 37 | return sum; 38 | } 39 | int exampleFunction2() { return rand(); } 40 | int exampleFunction3(int a, int b, int c) { 41 | return exampleFunction2() * a * b * c; 42 | } 43 | void ultraOneLiner() { 44 | cout << "this should not be on a single line\n"; 45 | } 46 | void badFormatting() { 47 | for (int i = 0; i < 1000; i++) cout << i << endl; 48 | } 49 | -------------------------------------------------------------------------------- /content/misc/Mos.java: -------------------------------------------------------------------------------- 1 | class Mos { 2 | static int n, q, size; 3 | static int[] arr, out; 4 | static query[] qs; 5 | public static void main (String[] args){ 6 | size = (int)Math.sqrt(n); 7 | // currently algorithm will find the number of distinct integers in a range [l, r] 8 | int[] freq = new int[1_000_001]; 9 | int l = 0, r = -1; 10 | int ans = 0; 11 | for(query curr : qs){ 12 | int cl = curr.l, cr = curr.r; 13 | while(l > cl){ 14 | --l; 15 | ++freq[arr[l]]; 16 | if(freq[arr[l]] == 1) ++ans; 17 | } 18 | while(r < cr){ 19 | ++r; 20 | ++freq[arr[r]]; 21 | if(freq[arr[r]] == 1) ++ans; 22 | } 23 | while(l < cl){ 24 | --freq[arr[l]]; 25 | if(freq[arr[l]] == 0) --ans; 26 | ++l; 27 | } 28 | while(r > cr){ 29 | --freq[arr[r]]; 30 | if(freq[arr[r]] == 0) --ans; 31 | --r; 32 | } 33 | out[curr.i] = ans; 34 | } 35 | } 36 | static class query implements Comparable { 37 | int l, r, i, b; 38 | query(int ll, int rr, int ii){ 39 | l = ll; 40 | r = rr; 41 | i = ii; 42 | b = l / size; 43 | } 44 | public int compareTo(query in){ 45 | if(b != in.b) return b - in.b; 46 | if(b % 2 == 0) return r - in.r; 47 | return in.r - r; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /content/numerical/MatrixInverse.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Max Bennedich 3 | * Date: 2004-02-08 4 | * Description: Invert matrix $A$. Returns rank; result is stored in $A$ unless singular (rank < n). 5 | * Can easily be extended to prime moduli; for prime powers, repeatedly 6 | * set $A^{-1} = A^{-1} (2I - AA^{-1})\ (\text{mod }p^k)$ where $A^{-1}$ starts as 7 | * the inverse of A mod p, and k is doubled in each step. 8 | * Time: O(n^3) 9 | * Status: Slightly tested 10 | */ 11 | #pragma once 12 | int matInv(vector>& A) { 13 | int n = sz(A); 14 | vi col(n); 15 | vector> tmp(n, vector(n)); 16 | rep (i, 0, n) tmp[i][i] = 1, col[i] = i; 17 | rep (i, 0, n) { 18 | int r = i, c = i; 19 | rep (j, i, n) rep (k, i, n) 20 | if (fabs(A[j][k]) > fabs(A[r][c])) r = j, c = k; 21 | if (fabs(A[r][c]) < 1e-12) return i; 22 | A[i].swap(A[r]); 23 | tmp[i].swap(tmp[r]); 24 | rep (j, 0, n) 25 | swap(A[j][i], A[j][c]), swap(tmp[j][i], tmp[j][c]); 26 | swap(col[i], col[c]); 27 | double v = A[i][i]; 28 | rep (j, i + 1, n) { 29 | double f = A[j][i] / v; 30 | A[j][i] = 0; 31 | rep (k, i + 1, n) A[j][k] -= f * A[i][k]; 32 | rep (k, 0, n) tmp[j][k] -= f * tmp[i][k]; } 33 | rep (j, i + 1, n) A[i][j] /= v; 34 | rep (j, 0, n) tmp[i][j] /= v; 35 | A[i][i] = 1; } 36 | /// forget A at this point, just eliminate tmp backward 37 | for (int i = n - 1; i > 0; --i) rep (j, 0, i) { 38 | double v = A[j][i]; 39 | rep (k, 0, n) tmp[j][k] -= v * tmp[i][k]; } 40 | rep (i, 0, n) rep (j, 0, n) A[col[i]][col[j]] = tmp[i][j]; 41 | return n; } 42 | -------------------------------------------------------------------------------- /content/numerical/FastFourierTransformMod.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: chilli 3 | * Date: 2019-04-25 4 | * License: CC0 5 | * Source: http://neerc.ifmo.ru/trains/toulouse/2017/fft2.pdf 6 | * Description: Higher precision FFT, can be used for convolutions modulo arbitrary integers 7 | * as long as $N\log_2N\cdot \text{mod} < 8.6 \cdot 10^{14}$ (in practice $10^{16}$ or higher). 8 | * Inputs must be in $[0, \text{mod})$. 9 | * Time: O(N \log N), where $N = |A|+|B|$ (twice as slow as NTT or FFT) 10 | * Status: stress-tested 11 | * Details: An in-depth examination of precision for both FFT and FFTMod can be found 12 | * here (https://github.com/simonlindholm/fft-precision/blob/master/fft-precision.md) 13 | */ 14 | #pragma once 15 | #include "FastFourierTransform.h" 16 | typedef vector vl; 17 | template vl convMod(const vl &a, const vl &b) { 18 | if (a.empty() || b.empty()) return {}; 19 | vl res(sz(a) + sz(b) - 1); 20 | int B = 32 - __builtin_clz(sz(res)), n = 1 << B, 21 | cut = int(sqrt(M)); 22 | vector L(n), R(n), outs(n), outl(n); 23 | rep(i, 0, sz(a)) L[i] = C((int)a[i] / cut, (int)a[i] % cut); 24 | rep(i, 0, sz(b)) R[i] = C((int)b[i] / cut, (int)b[i] % cut); 25 | fft(L), fft(R); 26 | rep(i, 0, n) { 27 | int j = -i & (n - 1); 28 | outl[j] = (L[i] + conj(L[j])) * R[i] / (2.0 * n); 29 | outs[j] = (L[i] - conj(L[j])) * R[i] / (2.0 * n) / 1i; 30 | } 31 | fft(outl), fft(outs); 32 | rep(i, 0, sz(res)) { 33 | ll av = ll(real(outl[i]) + .5), 34 | cv = ll(imag(outs[i]) + .5); 35 | ll bv = ll(imag(outl[i]) + .5) + ll(real(outs[i]) + .5); 36 | res[i] = ((av % M * cut + bv) % M * cut + cv) % M; 37 | } 38 | return res; 39 | } 40 | -------------------------------------------------------------------------------- /content/combinatorial/schreier-sims.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: THU 3 | * Description: Check group membership of permutation groups 4 | */ 5 | struct Perm { 6 | int a[N]; 7 | Perm() { 8 | for (int i = 1; i <= n; ++i) a[i] = i; 9 | } 10 | friend Perm operator*(const Perm &lhs, const Perm &rhs) { 11 | static Perm res; 12 | for (int i = 1; i <= n; ++i) res.a[i] = lhs.a[rhs.a[i]]; 13 | return res; 14 | } 15 | friend Perm inv(const Perm &cur) { 16 | static Perm res; 17 | for (int i = 1; i <= n; ++i) res.a[cur.a[i]] = i; 18 | return res; 19 | } 20 | }; 21 | class Group { 22 | bool flag[N]; 23 | Perm w[N]; 24 | std::vector x; 25 | public: 26 | void clear(int p) { 27 | memset(flag, 0, sizeof flag); 28 | for (int i = 1; i <= n; ++i) w[i] = Perm(); 29 | flag[p] = true; 30 | x.clear(); 31 | } 32 | friend bool check(const Perm &, int); 33 | friend void insert(const Perm &, int); 34 | friend void updateX(const Perm &, int); 35 | } g[N]; 36 | bool check(const Perm &cur, int k) { 37 | if (!k) return true; 38 | int t = cur.a[k]; 39 | return g[k].flag[t] ? check(g[k].w[t] * cur, k - 1) : false; 40 | } 41 | void updateX(const Perm &, int); 42 | void insert(const Perm &cur, int k) { 43 | if (check(cur, k)) return; 44 | g[k].x.push_back(cur); 45 | for (int i = 1; i <= n; ++i) 46 | if (g[k].flag[i]) updateX(cur * inv(g[k].w[i]), k); 47 | } 48 | void updateX(const Perm &cur, int k) { 49 | int t = cur.a[k]; 50 | if (g[k].flag[t]) { 51 | insert(g[k].w[t] * cur, k - 1); 52 | } else { 53 | g[k].w[t] = inv(cur); 54 | g[k].flag[t] = true; 55 | for (int i = 0; i < g[k].x.size(); ++i) 56 | updateX(g[k].x[i] * cur, k); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /content/number-theory/mobius.tex: -------------------------------------------------------------------------------- 1 | \subsection{Multiplicative Functions} 2 | A function $f : \mathbb{N} \to \mathbb{C}$ is multiplicative if 3 | $f(ab) = f(a)f(b)$ when $a, b$ are coprime. 4 | Common multiplicative functions: \\ 5 | Unit function: $\epsilon(n) = [n = 1]$ \\ 6 | Constant function: $1(n) = 1$ \\ 7 | Identity function: $\mathrm{Id}(n) = n$ \\ 8 | Power function: $\mathrm{Id}_a(n) = n^a$ \\ 9 | Divisor function $\sigma_a(p^k) = \frac{p^{a(k+1)} - 1}{p^a - 1}$ \\ 10 | Möbius function $\mu(p^k) = [k = 0] - [k = 1]$ \\ 11 | Euler's totient function $\phi(p^k) = p^k - p^{k-1}$ \\ 12 | Dirichlet convolution of multiplicative functions $f$ and $g$ is multiplicative, 13 | \[ (f*g)(n) = \sum_{d \mid n} f(d) g\left(\frac{n}{d}\right) \] 14 | \begin{center} 15 | \begin{tabular}{ c c c } 16 | $1 * \mu = \epsilon$ & $g = f * 1$ iff $f = g * \mu$ & $\sigma_k = \mathrm{Id}_k * 1$ \\ 17 | $\sigma_0 = d = 1 * 1$ & $\phi * 1 = \mathrm{Id}$ & $\phi^k * 1 = \mathrm{Id}_k$ \\ 18 | $\sigma = \phi * d$ & $d^3 * 1 = (d * 1)^2$ & 19 | \end{tabular} 20 | \end{center} 21 | $\pi(x) = \sum_{n \leq x} (\omega * \mu)(n)$, $\pi = $ prime counting function, $\omega = $ num. of prime factors \\ 22 | \subsection{Möbius Inversion Formula} 23 | If for any two functions $f, g : \mathbb{N} \to \mathbb{C}$, $g(n) = \sum_{d \mid n} f(n)$, 24 | \[ f(n) = (\mu * g)(n) = \sum_{d \mid n} \mu(d) g \left(\frac{n}{d}\right) \] 25 | \subsection{Inverse of Large Factorials} 26 | Hardcoded Factorial Inverses to avoid having to type modpow. $MAX = 5\cdot10^6$ 27 | $ invfact[MAX] mod 998244353 = 310402238 $ 28 | $ invfact[MAX] mod 1000000007 = 255895843 $ 29 | -------------------------------------------------------------------------------- /content/crackpack/Mos.java: -------------------------------------------------------------------------------- 1 | class Mos { 2 | static int n, q, size; 3 | static int[] arr, out; 4 | static query[] qs; 5 | public static void main (String[] args){ 6 | size = (int)Math.sqrt(n); 7 | 8 | // currently algorithm will find the number of distinct integers in a range [l, r] 9 | 10 | int[] freq = new int[1_000_001]; 11 | int l = 0, r = -1; 12 | int ans = 0; 13 | for(query curr : qs){ 14 | int cl = curr.l, cr = curr.r; 15 | 16 | while(l > cl){ 17 | --l; 18 | ++freq[arr[l]]; 19 | if(freq[arr[l]] == 1) ++ans; 20 | } 21 | while(r < cr){ 22 | ++r; 23 | ++freq[arr[r]]; 24 | if(freq[arr[r]] == 1) ++ans; 25 | } 26 | while(l < cl){ 27 | --freq[arr[l]]; 28 | if(freq[arr[l]] == 0) --ans; 29 | ++l; 30 | } 31 | while(r > cr){ 32 | --freq[arr[r]]; 33 | if(freq[arr[r]] == 0) --ans; 34 | --r; 35 | } 36 | 37 | out[curr.i] = ans; 38 | } 39 | 40 | } 41 | static class query implements Comparable { 42 | int l, r, i, b; 43 | query(int ll, int rr, int ii){ 44 | l = ll; 45 | r = rr; 46 | i = ii; 47 | b = l / size; 48 | } 49 | public int compareTo(query in){ 50 | if(b != in.b) return b - in.b; 51 | if(b % 2 == 0) return r - in.r; 52 | return in.r - r; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /content/geometry/SegmentIntersection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Victor Lecomte, chilli 3 | * Date: 2019-04-27 4 | * License: CC0 5 | * Source: https://vlecomte.github.io/cp-geo.pdf 6 | * Description:\\ 7 | \begin{minipage}{75mm} 8 | If a unique intersection point between the line segments going from s1 to e1 and from s2 to e2 exists then it is returned. 9 | If no intersection point exists an empty vector is returned. If infinitely many exist a vector with 2 elements is returned, containing the endpoints of the common line segment. 10 | The wrong position will be returned if P is Point and the intersection point does not have integer coordinates. 11 | Products of three coordinates are used in intermediate steps so watch out for overflow if using int or long long. 12 | \end{minipage} 13 | \begin{minipage}{15mm} 14 | \includegraphics[width=\textwidth]{content/geometry/SegmentIntersection} 15 | \end{minipage} 16 | * Usage: 17 | * vector

inter = segInter(s1,e1,s2,e2); 18 | * if (sz(inter)==1) 19 | * cout << "segments intersect at " << inter[0] << endl; 20 | * Status: stress-tested, tested on kattis:intersection 21 | */ 22 | #pragma once 23 | #include "Point.h" 24 | #include "OnSegment.h" 25 | template vector

segInter(P a, P b, P c, P d) { 26 | auto oa = c.cross(d, a), ob = c.cross(d, b), 27 | oc = a.cross(b, c), od = a.cross(b, d); 28 | // Checks if intersection is single non-endpoint point. 29 | if (sgn(oa) * sgn(ob) < 0 && sgn(oc) * sgn(od) < 0) 30 | return {(a * ob - b * oa) / (ob - oa)}; 31 | set

s; 32 | if (onSegment(c, d, a)) s.insert(a); 33 | if (onSegment(c, d, b)) s.insert(b); 34 | if (onSegment(a, b, c)) s.insert(c); 35 | if (onSegment(a, b, d)) s.insert(d); 36 | return {all(s)}; } 37 | -------------------------------------------------------------------------------- /content/crackpack/SegTree.java: -------------------------------------------------------------------------------- 1 | static class ST{ 2 | 3 | int n; 4 | int[] lo; 5 | int[] hi; 6 | long[] sum; 7 | long[] lazy; 8 | 9 | public ST(int nn){ 10 | n = nn; 11 | lo = new int[n*4+1]; 12 | hi = new int[n*4+1]; 13 | sum = new long[n*4+1]; 14 | lazy = new long[n*4+1]; 15 | build(1, 0, n-1); 16 | } 17 | 18 | void build(int i, int a, int b){ 19 | lo[i] = a; 20 | hi[i] = b; 21 | if(a == b) return; 22 | int m = (a+b)/2; 23 | build(2*i, a, m); 24 | build(2*i+1, m+1, b); 25 | } 26 | 27 | void prop(int i){ 28 | sum[2*i] += (hi[2*i]-lo[2*i]+1)*lazy[i]; 29 | sum[2*i+1] += (hi[2*i+1]-lo[2*i+1]+1)*lazy[i]; 30 | lazy[2*i] += lazy[i]; 31 | lazy[2*i+1] += lazy[i]; 32 | lazy[i] = 0; 33 | } 34 | 35 | void add(int l, int r, long v){ 36 | if(l > r){ 37 | add(1, l, n-1, v); 38 | add(1, 0, r, v); 39 | } 40 | else{ 41 | add(1, l, r, v); 42 | } 43 | } 44 | 45 | void add(int i, int l, int r, long v){ 46 | if(r < lo[i] || l > hi[i]) return; 47 | if(l <= lo[i] && hi[i] <= r){ 48 | lazy[i] += v; 49 | sum[i] += (hi[i]-lo[i]+1)*v; 50 | return; 51 | } 52 | prop(i); 53 | add(2*i, l, r, v); 54 | add(2*i+1, l, r, v); 55 | sum[i] = sum[2*i]+sum[2*i+1]; 56 | } 57 | 58 | long sum(int l, int r){ 59 | if(l > r){ 60 | return sum(1, l, n-1)+sum(1, 0, r); 61 | } 62 | else{ 63 | return sum(1, l, r); 64 | } 65 | } 66 | 67 | long sum(int i, int l, int r){ 68 | if(r < lo[i] || l > hi[i]) return 0; 69 | if(l <= lo[i] && hi[i] <= r){ 70 | return sum[i]; 71 | } 72 | prop(i); 73 | long res = 0; 74 | res += sum(2*i, l, r); 75 | res += sum(2*i+1, l, r); 76 | return res; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /content/numerical/MatrixInverse-mod.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2016-12-08 4 | * Source: The regular matrix inverse code 5 | * Description: Invert matrix $A$ modulo a prime. 6 | * Returns rank; result is stored in $A$ unless singular (rank < n). 7 | * For prime powers, repeatedly set $A^{-1} = A^{-1} (2I - AA^{-1})\ (\text{mod }p^k)$ where $A^{-1}$ starts as 8 | * the inverse of A mod p, and k is doubled in each step. 9 | * Time: O(n^3) 10 | * Status: Slightly tested 11 | */ 12 | #pragma once 13 | #include "../number-theory/ModPow.h" 14 | int matInv(vector>& A) { 15 | int n = sz(A); 16 | vi col(n); 17 | vector> tmp(n, vector(n)); 18 | rep(i, 0, n) tmp[i][i] = 1, col[i] = i; 19 | rep(i, 0, n) { 20 | int r = i, c = i; 21 | rep(j, i, n) rep(k, i, n) if (A[j][k]) { 22 | r = j; 23 | c = k; 24 | goto found; 25 | } 26 | return i; 27 | found: 28 | A[i].swap(A[r]); 29 | tmp[i].swap(tmp[r]); 30 | rep(j, 0, n) swap(A[j][i], A[j][c]), 31 | swap(tmp[j][i], tmp[j][c]); 32 | swap(col[i], col[c]); 33 | ll v = modpow(A[i][i], mod - 2); 34 | rep(j, i + 1, n) { 35 | ll f = A[j][i] * v % mod; 36 | A[j][i] = 0; 37 | rep(k, i + 1, n) A[j][k] = (A[j][k] - f * A[i][k]) % mod; 38 | rep(k, 0, n) tmp[j][k] = 39 | (tmp[j][k] - f * tmp[i][k]) % mod; 40 | } 41 | rep(j, i + 1, n) A[i][j] = A[i][j] * v % mod; 42 | rep(j, 0, n) tmp[i][j] = tmp[i][j] * v % mod; 43 | A[i][i] = 1; 44 | } 45 | for (int i = n - 1; i > 0; --i) rep(j, 0, i) { 46 | ll v = A[j][i]; 47 | rep(k, 0, n) tmp[j][k] = 48 | (tmp[j][k] - v * tmp[i][k]) % mod; 49 | } 50 | rep(i, 0, n) rep(j, 0, n) A[col[i]][col[j]] = 51 | tmp[i][j] % mod + (tmp[i][j] < 0 ? mod : 0); 52 | return n; 53 | } 54 | -------------------------------------------------------------------------------- /content/graphs/WeightedMatching.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Benjamin Qi, chilli 3 | * Date: 2020-04-04 4 | * License: CC0 5 | * Source: https://github.com/bqi343/USACO/blob/master/Implementations/content/graphs%20(12)/Matching/Hungarian.h 6 | * Description: Given a weighted bipartite graph, matches every node on 7 | * the left with a node on the right such that no 8 | * nodes are in two matchings and the sum of the edge weights is minimal. Takes 9 | * cost[N][M], where cost[i][j] = cost for L[i] to be matched with R[j] and 10 | * returns (min cost, match), where L[i] is matched with 11 | * R[match[i]]. Negate costs for max cost. Requires $N \le M$. 12 | * Time: O(N^2M) 13 | * Status: Tested on kattis:cordonbleu, stress-tested 14 | */ 15 | #pragma once 16 | pair hungarian(const vector& a) { 17 | if (a.empty()) return {0, {}}; 18 | int n = sz(a) + 1, m = sz(a[0]) + 1; 19 | vi u(n), v(m), p(m), ans(n - 1); 20 | rep (i, 1, n) { 21 | p[0] = i; 22 | int j0 = 0; // add "dummy" worker 0 23 | vi dist(m, INT_MAX), pre(m, -1); 24 | vector done(m + 1); 25 | do { // dijkstra 26 | done[j0] = true; 27 | int i0 = p[j0], j1, delta = INT_MAX; 28 | rep (j, 1, m) if (!done[j]) { 29 | auto cur = a[i0 - 1][j - 1] - u[i0] - v[j]; 30 | if (cur < dist[j]) dist[j] = cur, pre[j] = j0; 31 | if (dist[j] < delta) delta = dist[j], j1 = j; } 32 | rep (j, 0, m) { 33 | if (done[j]) u[p[j]] += delta, v[j] -= delta; 34 | else dist[j] -= delta; } 35 | j0 = j1; } while (p[j0]); 36 | while (j0) { // update alternating path 37 | int j1 = pre[j0]; 38 | p[j0] = p[j1], j0 = j1; } } 39 | rep (j, 1, m) if (p[j]) ans[p[j] - 1] = j - 1; 40 | return {-v[0], ans}; // min cost 41 | } 42 | -------------------------------------------------------------------------------- /content/graphs/KactlDinic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: chilli 3 | * Date: 2019-04-26 4 | * License: CC0 5 | * Source: https://cp-algorithms.com/graph/dinic.html 6 | * Description: Flow algorithm with complexity $O(VE\log U)$ where $U = \max |\text{cap}|$. 7 | * $O(\min(E^{1/2}, V^{2/3})E)$ if $U = 1$; $O(\sqrt{V}E)$ for bipartite matching. 8 | * Status: Tested on SPOJ FASTFLOW and SPOJ MATCHING, stress-tested 9 | */ 10 | #pragma once 11 | struct Dinic { 12 | struct Edge { 13 | int to, rev; 14 | ll c, oc; 15 | ll flow() { return max(oc - c, 0LL); } // if you need flows 16 | }; 17 | vi lvl, ptr, q; 18 | vector> adj; 19 | Dinic(int n): lvl(n), ptr(n), q(n), adj(n) {} 20 | void addEdge(int a, int b, ll c, ll rcap = 0) { 21 | adj[a].push_back({b, sz(adj[b]), c, c}); 22 | adj[b].push_back({a, sz(adj[a]) - 1, rcap, rcap}); 23 | } 24 | ll dfs(int v, int t, ll f) { 25 | if (v == t || !f) return f; 26 | for (int& i = ptr[v]; i < sz(adj[v]); i++) { 27 | Edge& e = adj[v][i]; 28 | if (lvl[e.to] == lvl[v] + 1) 29 | if (ll p = dfs(e.to, t, min(f, e.c))) { 30 | e.c -= p, adj[e.to][e.rev].c += p; 31 | return p; 32 | } 33 | } 34 | return 0; 35 | } 36 | ll calc(int s, int t) { 37 | ll flow = 0; 38 | q[0] = s; 39 | rep(L, 0, 40 | 31) do { // 'int L=30' maybe faster for random data 41 | lvl = ptr = vi(sz(q)); 42 | int qi = 0, qe = lvl[s] = 1; 43 | while (qi < qe && !lvl[t]) { 44 | int v = q[qi++]; 45 | for (Edge e : adj[v]) 46 | if (!lvl[e.to] && e.c >> (30 - L)) 47 | q[qe++] = e.to, lvl[e.to] = lvl[v] + 1; 48 | } 49 | while (ll p = dfs(s, t, LLONG_MAX)) flow += p; 50 | } 51 | while (lvl[t]) 52 | ; 53 | return flow; 54 | } 55 | bool leftOfMinCut(int a) { return lvl[a] != 0; } 56 | }; 57 | -------------------------------------------------------------------------------- /content/geometry/Point.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Ulf Lundstrom 3 | * Date: 2009-02-26 4 | * License: CC0 5 | * Source: My head with inspiration from tinyKACTL 6 | * Description: Class to handle points in the plane. 7 | * T can be e.g. double or long long. (Avoid int.) 8 | * Status: Works fine, used a lot 9 | */ 10 | #pragma once 11 | template int sgn(T x) { return (x > 0) - (x < 0); } 12 | template struct Point { 13 | typedef Point P; 14 | T x, y; 15 | explicit Point(T x = 0, T y = 0): x(x), y(y) {} 16 | bool 17 | operator<(P p) const { return tie(x, y) < tie(p.x, p.y); } 18 | bool 19 | operator==(P p) const { return tie(x, y) == tie(p.x, p.y); } 20 | P operator+(P p) const { return P(x + p.x, y + p.y); } 21 | P operator-(P p) const { return P(x - p.x, y - p.y); } 22 | P operator*(T d) const { return P(x * d, y * d); } 23 | P operator/(T d) const { return P(x / d, y / d); } 24 | T dot(P p) const { return x * p.x + y * p.y; } 25 | T cross(P p) const { return x * p.y - y * p.x; } 26 | T cross(P a, P b) const { 27 | return (a - *this).cross(b - *this); } 28 | T dist2() const { return x * x + y * y; } 29 | double dist() const { return sqrt((double)dist2()); } 30 | // angle to x-axis in interval [-pi, pi] 31 | double angle() const { return atan2(y, x); } 32 | P unit() const { return *this / dist(); } // makes dist()=1 33 | P perp() const { return P(-y, x); } // rotates +90 degrees 34 | P normal() const { return perp().unit(); } 35 | // returns point rotated 'a' radians ccw around the origin 36 | P rotate(double a) const { 37 | return P(x * cos(a) - y * sin(a), 38 | x * sin(a) + y * cos(a)); } 39 | friend ostream& operator<<(ostream& os, P p) { 40 | return os << "(" << p.x << "," << p.y << ")"; } }; 41 | -------------------------------------------------------------------------------- /tests/graphs/SCCTarjan.cpp: -------------------------------------------------------------------------------- 1 | // Tested on https://codeforces.com/problemset/problem/427/C 2 | 3 | #include 4 | using namespace std; 5 | 6 | using ll = long long; 7 | 8 | #include "../../content/graphs/SCCTarjan.h" 9 | 10 | int main() { 11 | cin.tie(0)->sync_with_stdio(0); 12 | cin.exceptions(cin.failbit); 13 | 14 | const ll MOD = 1000000007; 15 | 16 | int n; 17 | cin >> n; 18 | 19 | vector cost(n); 20 | for (int& x : cost) cin >> x; 21 | 22 | vector> adj(n); 23 | int m; 24 | cin >> m; 25 | 26 | for (int i = 0; i < m; i++) { 27 | int u, v; 28 | cin >> u >> v; 29 | adj[u - 1].push_back(v - 1); 30 | } 31 | 32 | ll ans1 = 0, ways1 = 1; 33 | 34 | // solve using the lambda 35 | SCCTarjan::scc(adj, [&](vector& v) { 36 | int add = (int)1e9 + 10; 37 | int cnt = 0; 38 | 39 | for (int i : v) 40 | if (cost[i] < add) { 41 | add = cost[i]; 42 | cnt = 1; 43 | } else if (cost[i] == add) 44 | cnt++; 45 | 46 | ans1 += add; 47 | ways1 = (ways1 * cnt) % MOD; 48 | }); 49 | 50 | // solve using the component IDs 51 | vector comp = SCCTarjan::scc(adj); 52 | vector add(comp.size(), (int)1e9 + 10), cnt(comp.size(), 1); 53 | ll ans2 = 0, ways2 = 1; 54 | int ncomps = 0; 55 | 56 | for (int i = 0; i < n; i++) { 57 | ncomps = max(ncomps, comp[i] + 1); 58 | 59 | if (cost[i] < add[comp[i]]) { 60 | add[comp[i]] = cost[i]; 61 | cnt[comp[i]] = 1; 62 | } else if (cost[i] == add[comp[i]]) 63 | cnt[comp[i]]++; 64 | } 65 | 66 | for (int i = 0; i < ncomps; i++) ans2 += add[i]; 67 | for (int i = 0; i < ncomps; i++) ways2 = (ways2 * cnt[i]) % MOD; 68 | 69 | // show both ways work 70 | assert(ans1 == ans2); 71 | assert(ways1 == ways2); 72 | 73 | cout << ans1 << " " << ways1 << '\n'; 74 | } 75 | -------------------------------------------------------------------------------- /content/data-structures/LazyIterativeSegTree.h: -------------------------------------------------------------------------------- 1 | template 3 | struct lazy_segtree { 4 | int N, log, S; 5 | vector d; 6 | vector lz; 7 | lazy_segtree(const vector& v): 8 | N(sz(v)), log(__lg(2 * N - 1)), S(1 << log), d(2 * S, e()), 9 | lz(S, id()) { 10 | for (int i = 0; i < N; i++) d[S + i] = v[i]; 11 | for (int i = S - 1; i >= 1; i--) pull(i); 12 | } 13 | void apply(int k, F f) { 14 | d[k] = onto(f, d[k]); 15 | if (k < S) lz[k] = comp(f, lz[k]); 16 | } 17 | void push(int k) { 18 | apply(2 * k, lz[k]), apply(2 * k + 1, lz[k]), lz[k] = id(); 19 | } 20 | void push(int l, int r) { 21 | int zl = __builtin_ctz(l), zr = __builtin_ctz(r); 22 | for (int i = log; i > min(zl, zr); i--) { 23 | if (i > zl) push(l >> i); 24 | if (i > zr) push((r - 1) >> i); 25 | } 26 | } 27 | void pull(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } 28 | void set(int p, T x) { 29 | p += S; 30 | for (int i = log; i >= 1; i--) push(p >> i); 31 | for (d[p] = x; p /= 2;) pull(p); 32 | } 33 | T query(int l, int r) { 34 | if (l == r) return T{}; 35 | push(l += S, r += S); 36 | T vl = e(), vr = e(); 37 | for (; l < r; l /= 2, r /= 2) { 38 | if (l & 1) vl = op(vl, d[l++]); 39 | if (r & 1) vr = op(d[--r], vr); 40 | } 41 | return op(vl, vr); 42 | } 43 | void update(int l, int r, F f) { 44 | if (l == r) return; 45 | push(l += S, r += S); 46 | for (int a = l, b = r; a < b; a /= 2, b /= 2) { 47 | if (a & 1) apply(a++, f); 48 | if (b & 1) apply(--b, f); 49 | } 50 | int zl = __builtin_ctz(l), zr = __builtin_ctz(r); 51 | for (int i = min(zl, zr) + 1; i <= log; i++) { 52 | if (i > zl) pull(l >> i); 53 | if (i > zr) pull((r - 1) >> i); 54 | } 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /content/number-theory/ModInt.h: -------------------------------------------------------------------------------- 1 | template struct mint { 2 | using mr = const mint&; 3 | int v; 4 | explicit operator int() const { return v; } 5 | // explicit -> don't silently convert to int 6 | mint(ll _v = 0) { 7 | v = int((-MOD < _v && _v < MOD) ? _v : _v % MOD); 8 | if (v < 0) v += MOD; } 9 | mint& operator+=(mr o) { 10 | if ((v += o.v) >= MOD) v -= MOD; 11 | return *this; } 12 | mint& operator-=(mr o) { 13 | if ((v -= o.v) < 0) v += MOD; 14 | return *this; } 15 | mint& operator*=(mr o) { 16 | v = int(ll(v) * o.v % MOD); 17 | return *this; } 18 | mint& operator/=(mr o) { return (*this) *= inv(o); } 19 | friend mint pow(mint a, ll p) { 20 | mint ans = 1; 21 | assert(p >= 0); 22 | for (; p; p /= 2, a *= a) if (p & 1) ans *= a; 23 | return ans; } 24 | friend mint 25 | inv(mr a) { assert(a.v != 0); return pow(a, MOD - 2); } 26 | friend mint operator+(mint a, mr b) { return a += b; } 27 | friend mint operator-(mint a, mr b) { return a -= b; } 28 | friend mint operator*(mint a, mr b) { return a *= b; } 29 | friend mint operator/(mint a, mr b) { return a /= b; } 30 | bool operator==(mr o) const { return v == o.v; } 31 | friend bool operator!=(mr a, mr b) { return !(a == b); } 32 | friend bool operator<(mr a, mr b) { return a.v < b.v; } 33 | mint operator-() const { return mint(-v); } 34 | mint& operator++() { return *this += 1; } 35 | mint& operator--() { return *this -= 1; } 36 | friend istream& operator>>(istream& is, mint& a) { 37 | return is >> a.v; } 38 | friend ostream& operator<<(ostream& os, const mint& a) { 39 | return os << a.v; } 40 | static constexpr mint rt() { return RT; } 41 | // primitive root for FFT 42 | }; 43 | using mi = mint; 44 | // 5 is primitive root for both common mods 45 | -------------------------------------------------------------------------------- /content/graphs/EdgeColoring.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2020-10-12 4 | * License: CC0 5 | * Source: https://en.wikipedia.org/wiki/Misra_%26_Gries_edge_coloring_algorithm 6 | * https://codeforces.com/blog/entry/75431 for the note about bipartite graphs. 7 | * Description: Given a simple, undirected graph with max degree $D$, computes a 8 | * $(D + 1)$-coloring of the edges such that no neighboring edges share a color. 9 | * ($D$-coloring is NP-hard, but can be done for bipartite graphs by repeated matchings of 10 | * max-degree nodes.) 11 | * Time: O(NM) 12 | * Status: stress-tested, tested on kattis:gamescheduling 13 | */ 14 | #pragma once 15 | vi edgeColoring(int N, vector eds) { 16 | vi cc(N + 1), ret(sz(eds)), fan(N), free(N), loc; 17 | for (pii e : eds) ++cc[e.first], ++cc[e.second]; 18 | int u, v, ncols = *max_element(all(cc)) + 1; 19 | vector adj(N, vi(ncols, -1)); 20 | for (pii e : eds) { 21 | tie(u, v) = e; 22 | fan[0] = v; 23 | loc.assign(ncols, 0); 24 | int at = u, end = u, d, c = free[u], ind = 0, i = 0; 25 | while (d = free[v], !loc[d] && (v = adj[u][d]) != -1) 26 | loc[d] = ++ind, cc[ind] = d, fan[ind] = v; 27 | cc[loc[d]] = c; 28 | for (int cd = d; at != -1; cd ^= c ^ d, at = adj[at][cd]) 29 | swap(adj[at][cd], adj[end = at][cd ^ c ^ d]); 30 | while (adj[fan[i]][d] != -1) { 31 | int left = fan[i], right = fan[++i], e = cc[i]; 32 | adj[u][e] = left; 33 | adj[left][e] = u; 34 | adj[right][e] = -1; 35 | free[right] = e; } 36 | adj[u][d] = fan[i]; 37 | adj[fan[i]][d] = u; 38 | for (int y : {fan[0], u, end}) 39 | for (int& z = free[y] = 0; adj[y][z] != -1; z++) ; } 40 | rep (i, 0, sz(eds)) 41 | for (tie(u, v) = eds[i]; adj[u][ret[i]] != v; ) ++ret[i]; 42 | return ret; } 43 | -------------------------------------------------------------------------------- /content/strings/SuffixArray.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: 罗穗骞, chilli 3 | * Date: 2019-04-11 4 | * License: Unknown 5 | * Source: Suffix array - a powerful tool for dealing with strings 6 | * (Chinese IOI National team training paper, 2009) 7 | * Description: Builds suffix array for a string. 8 | * \texttt{sa[i]} is the starting index of the suffix which 9 | * is $i$'th in the sorted suffix array. 10 | * The returned vector is of size $n+1$, and \texttt{sa[0] = n}. 11 | * The \texttt{lcp} array contains longest common prefixes for 12 | * neighbouring strings in the suffix array: 13 | * \texttt{lcp[i] = lcp(sa[i], sa[i-1])}, \texttt{lcp[0] = 0}. 14 | * The input string must not contain any zero bytes. 15 | * Time: O(n \log n) 16 | * Status: stress-tested 17 | */ 18 | #pragma once 19 | struct SuffixArray { 20 | vi sa, lcp, rank; 21 | SuffixArray(string& s, int lim = 256) { // basic_string 22 | int n = sz(s) + 1, k = 0, a, b; 23 | vi x(all(s) + 1), y(n), ws(max(n, lim)); 24 | sa = lcp = rank = y, iota(all(sa), 0); 25 | for (int j = 0, 26 | p = 0; p < n; j = max(1, j * 2), lim = p) { 27 | p = j, iota(all(y), n - j); 28 | rep (i, 0, n) if (sa[i] >= j) y[p++] = sa[i] - j; 29 | fill(all(ws), 0); 30 | rep (i, 0, n) ws[x[i]]++; 31 | rep (i, 1, lim) ws[i] += ws[i - 1]; 32 | for (int i = n; i--; ) sa[--ws[x[y[i]]]] = y[i]; 33 | swap(x, y), p = 1, x[sa[0]] = 0; 34 | rep (i, 1, n) 35 | a = sa[i - 1], b = sa[i], 36 | x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? p - 1 37 | : p++; } 38 | rep (i, 0, n) rank[sa[i]] = i; 39 | for (int i = 0, j; i < n - 1; lcp[rank[i++]] = k) 40 | for (k && k--, 41 | j = sa[rank[i] - 1]; s[i + k] == s[j + k]; k++) ; } 42 | }; 43 | -------------------------------------------------------------------------------- /content/strings/Hashing.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Simon Lindholm 3 | * Date: 2015-03-15 4 | * License: CC0 5 | * Source: own work 6 | * Description: Self-explanatory methods for string hashing. 7 | * Status: stress-tested 8 | */ 9 | #pragma once 10 | // Arithmetic mod 2^64-1. 2x slower than mod 2^64 and more 11 | // code, but works on evil test data (e.g. Thue-Morse, where 12 | // ABBA... and BAAB... of length 2^10 hash the same mod 2^64). 13 | // "typedef ull H;" instead if you think test data is random, 14 | // or work mod 10^9+7 if the Birthday paradox is not a problem. 15 | typedef uint64_t ull; 16 | struct H { 17 | ull x; 18 | H(ull x = 0): x(x) {} 19 | H operator+(H o) { return x + o.x + (x + o.x < x); } 20 | H operator-(H o) { return *this + ~o.x; } 21 | H operator*(H o) { 22 | auto m = (__uint128_t)x * o.x; 23 | return H((ull)m) + (ull)(m >> 64); } 24 | ull get() const { return x + !~x; } 25 | bool operator==(H o) const { return get() == o.get(); } 26 | bool operator<(H o) const { return get() < o.get(); } }; 27 | static const H C = (ll)1e11 + 3; 28 | // (order ~ 3e9; random also ok) 29 | struct HashInterval { 30 | vector ha, pw; 31 | HashInterval(string& str): ha(sz(str) + 1), pw(ha) { 32 | pw[0] = 1; 33 | rep (i, 0, sz(str)) 34 | ha[i + 1] = ha[i] * C + str[i], pw[i + 1] = pw[i] * C; } 35 | H hashInterval(int a, int b) { // hash [a, b) 36 | return ha[b] - ha[a] * pw[b - a]; } }; 37 | vector getHashes(string& str, int length) { 38 | if (sz(str) < length) return {}; 39 | H h = 0, pw = 1; 40 | rep (i, 0, length) h = h * C + str[i], pw = pw * C; 41 | vector ret = {h}; 42 | rep (i, length, sz(str)) { 43 | ret.push_back(h = h * C + str[i] - pw * str[i - length]); 44 | } 45 | return ret; } 46 | H hashString(string& s) { 47 | H h{}; 48 | for (char c : s) h = h * C + c; 49 | return h; } 50 | -------------------------------------------------------------------------------- /content/geometry/3dHull.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Johan Sannemo 3 | * Date: 2017-04-18 4 | * Source: derived from https://gist.github.com/msg555/4963794 by Mark Gordon 5 | * Description: Computes all faces of the 3-dimension hull of a point set. 6 | * *No four points must be coplanar*, or else random results will be returned. 7 | * All faces will point outwards. 8 | * Time: O(n^2) 9 | * Status: tested on SPOJ CH3D 10 | */ 11 | #pragma once 12 | #include "Point3D.h" 13 | typedef Point3D P3; 14 | struct PR { 15 | void ins(int x) { (a == -1 ? a : b) = x; } 16 | void rem(int x) { (a == x ? a : b) = -1; } 17 | int cnt() { return (a != -1) + (b != -1); } 18 | int a, b; 19 | }; 20 | struct F { 21 | P3 q; 22 | int a, b, c; 23 | }; 24 | vector hull3d(const vector& A) { 25 | assert(sz(A) >= 4); 26 | vector> E(sz(A), vector(sz(A), {-1, -1})); 27 | #define E(x, y) E[f.x][f.y] 28 | vector FS; 29 | auto mf = [&](int i, int j, int k, int l) { 30 | P3 q = (A[j] - A[i]).cross((A[k] - A[i])); 31 | if (q.dot(A[l]) > q.dot(A[i])) q = q * -1; 32 | F f{q, i, j, k}; 33 | E(a, b).ins(k), E(a, c).ins(j), E(b, c).ins(i); 34 | FS.push_back(f); 35 | }; 36 | rep(i, 0, 4) rep(j, i + 1, 4) rep(k, j + 1, 4) 37 | mf(i, j, k, 6 - i - j - k); 38 | rep(i, 4, sz(A)) { 39 | rep(j, 0, sz(FS)) { 40 | F f = FS[j]; 41 | if (f.q.dot(A[i]) > f.q.dot(A[f.a])) { 42 | E(a, b).rem(f.c), E(a, c).rem(f.b), E(b, c).rem(f.a); 43 | swap(FS[j--], FS.back()); 44 | FS.pop_back(); 45 | } 46 | } 47 | int nw = sz(FS); 48 | rep(j, 0, nw) { 49 | F f = FS[j]; 50 | #define C(a, b, c) \ 51 | if (E(a, b).cnt() != 2) mf(f.a, f.b, i, f.c); 52 | C(a, b, c), C(a, c, b), C(b, c, a); 53 | } 54 | } 55 | for (F& it : FS) 56 | if ( 57 | (A[it.b] - A[it.a]).cross(A[it.c] - A[it.a]).dot(it.q) <= 58 | 0) 59 | swap(it.c, it.b); 60 | return FS; 61 | }; 62 | -------------------------------------------------------------------------------- /content/geometry/PolygonUnion.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: black_horse2014, chilli 3 | * Date: 2019-10-29 4 | * License: Unknown 5 | * Source: https://codeforces.com/gym/101673/submission/50481926 6 | * Description: Calculates the area of the union of $n$ polygons (not necessarily 7 | * convex). The points within each polygon must be given in CCW order. 8 | * (Epsilon checks may optionally be added to sideOf/sgn, but shouldn't be needed.) 9 | * Time: $O(N^2)$, where $N$ is the total number of points 10 | * Status: stress-tested, Submitted on ECNA 2017 Problem A 11 | */ 12 | #pragma once 13 | #include "Point.h" 14 | #include "sideOf.h" 15 | typedef Point P; 16 | double rat(P a, P b) { 17 | return sgn(b.x) ? a.x / b.x : a.y / b.y; 18 | } 19 | double polyUnion(vector>& poly) { 20 | double ret = 0; 21 | rep(i, 0, sz(poly)) rep(v, 0, sz(poly[i])) { 22 | P A = poly[i][v], B = poly[i][(v + 1) % sz(poly[i])]; 23 | vector> segs = {{0, 0}, {1, 0}}; 24 | rep(j, 0, sz(poly)) if (i != j) { 25 | rep(u, 0, sz(poly[j])) { 26 | P C = poly[j][u], D = poly[j][(u + 1) % sz(poly[j])]; 27 | int sc = sideOf(A, B, C), sd = sideOf(A, B, D); 28 | if (sc != sd) { 29 | double sa = C.cross(D, A), sb = C.cross(D, B); 30 | if (min(sc, sd) < 0) 31 | segs.emplace_back(sa / (sa - sb), sgn(sc - sd)); 32 | } else if ( 33 | !sc && !sd && j < i && sgn((B - A).dot(D - C)) > 0) { 34 | segs.emplace_back(rat(C - A, B - A), 1); 35 | segs.emplace_back(rat(D - A, B - A), -1); 36 | } 37 | } 38 | } 39 | sort(all(segs)); 40 | for (auto& s : segs) s.first = min(max(s.first, 0.0), 1.0); 41 | double sum = 0; 42 | int cnt = segs[0].second; 43 | rep(j, 1, sz(segs)) { 44 | if (!cnt) sum += segs[j].first - segs[j - 1].first; 45 | cnt += segs[j].second; 46 | } 47 | ret += A.cross(B) * sum; 48 | } 49 | return ret / 2; 50 | } 51 | --------------------------------------------------------------------------------