├── Codes
├── .cproject
├── .gitignore
├── .project
├── CHIVO DELUXE EDITION (ACM_2012).pdf
├── DynamicProgramming
│ ├── ConvexHullTrick.cpp
│ ├── ConvexHullTrickSet.cpp
│ ├── ConvexHullTrickSet.cpp (Underwork)
│ ├── DynamicConvexHullTrick.cpp
│ ├── Histogram.cpp
│ ├── InversionCount.cpp
│ ├── LIS.cpp
│ ├── Partitions.cpp
│ ├── PersistentConvexHullTrick.cpp
│ └── SubsetSum.cpp
├── Geometry
│ ├── AngleBetweenVectors.cpp
│ ├── BestCurveBuffer.cpp
│ ├── ConvexHullUL.cpp
│ ├── Generic
│ │ ├── AllLineIntersections.cpp
│ │ ├── InsideSimplePolygon.cpp
│ │ ├── Line.cpp
│ │ ├── Point.cpp
│ │ ├── Polygon.cpp
│ │ └── VectorMethods.cpp
│ ├── Geometry.cpp
│ ├── InsideConvex.cpp
│ ├── PointStruct.cpp
│ ├── PointToPolygonProjector.cpp
│ ├── SegmentIntercect.cpp
│ └── ThirdPointLeft.cpp
├── Graph
│ ├── 2-SAT.cpp
│ ├── ConnectedComponnents.cpp
│ ├── CountMinimumSpanningTree.cpp
│ ├── CountSpanningTree.cpp
│ ├── EulerianPathAndCycle.cpp
│ ├── Flow
│ │ └── MinCostMaxFlow[AdjList].cpp
│ ├── HopcroftCarp.cpp
│ ├── HungarianAlgorithm.cpp
│ ├── MaxFlow[Dinics-EdgeList].cpp
│ ├── MaximumMatching.cpp
│ ├── NOT_WORKING_MincostMaxflow[AdjMatrix].cpp
│ ├── README.md
│ └── VertexCover.cpp
├── Math
│ ├── BigConvolutionFFT.cpp
│ ├── BigInteger.cpp
│ ├── BigPrimes.cpp
│ ├── BitVector.cpp
│ ├── Convolution.java
│ ├── DiscreteLogarithm-PollardRho.cpp
│ ├── DiscreteLogarithm.cpp
│ ├── EducationalFFT.cpp
│ ├── Equations
│ │ ├── BitGauss.cpp
│ │ ├── GaussDouble.cpp
│ │ └── VectorSpace.cpp
│ ├── Factors.cpp
│ ├── FastestFFT.cpp
│ ├── Fibo.cpp
│ ├── Fourier.cpp
│ ├── Fourier2.cpp
│ ├── Gauss.cpp
│ ├── GaussDouble.css
│ ├── GenericMatrix.cpp
│ ├── LinearCongruence.cpp
│ ├── LinearSieve.cpp
│ ├── Matrix.cpp
│ ├── ModInt.cpp
│ ├── ModIntShort.cpp
│ ├── NCR.cpp
│ ├── NTT.cpp
│ ├── NaiveCycleFinding.cpp
│ ├── Polinomial.cpp
│ └── PrimitiveRoot.cpp
├── String
│ ├── AhoCorasick.cpp
│ ├── CompressedTrie.cpp
│ ├── Hash.cpp
│ ├── KMP.cpp
│ ├── Manachers.cpp
│ ├── NextLetter.cpp
│ ├── RawHash.cpp
│ ├── StringUtils.cpp
│ ├── SubstringHash.cpp
│ ├── SuffixArray(NlogN).cpp
│ ├── SuffixArray.cpp
│ ├── SuffixArrayShort.cpp
│ ├── SuffixAutomaton.cpp
│ ├── SuffixTree(uses SuffixArray).cpp
│ └── Trie.cpp
├── Trees
│ ├── BalancedTrees
│ │ ├── VectorTreap.cpp
│ │ └── VectorTreapUpdate.cpp
│ ├── BlockedFenwick2D.cpp
│ ├── CentroidDecompShort.cpp
│ ├── CentroidDecomposition.cpp
│ ├── CompressedFenwick2D.cpp
│ ├── DinamycReversibleSegmentTree.cpp
│ ├── DisjointSet.cpp
│ ├── DynamicTrees
│ │ ├── EulerTree.cpp
│ │ ├── LinkCutTree.cpp
│ │ └── UpdatableEulerTourTree.cpp
│ ├── FEDisjointSet
│ ├── FenwickTree.cpp
│ ├── FragmentedTree.cpp
│ ├── HLD.cpp
│ ├── HeavyLightDecomposition.cpp
│ ├── HeavyLightDecomposition_SegmentTree.cpp
│ ├── ImplicitLazyPersistentSegmentTree.cpp
│ ├── ImplicitTree2D.cpp
│ ├── LCA.cpp
│ ├── LinkCutTreeLab.cpp
│ ├── Persistent
│ │ ├── PersistentArray.cpp
│ │ ├── PersistentFenwick.cpp
│ │ └── PersistentTrie.cpp
│ ├── PersistentSegmentTree.cpp
│ ├── RangeTrees.cpp
│ ├── SegmentTree.cpp
│ ├── SegmentTrees
│ │ ├── DynamicSegmentTree.cpp
│ │ ├── DynamicWavelet.cpp
│ │ ├── FastPersitenceSegmentTree.cpp
│ │ ├── FastSegmentTree.cpp
│ │ ├── ISegmentTree.cpp
│ │ ├── ISegmentTreeTrim.cpp
│ │ ├── PersistentDynamicSegmentTree.cpp
│ │ ├── PersistentSegmentTree.cpp
│ │ └── SegmentTree.cpp
│ ├── SortedSplayTree.cpp
│ ├── SparseTable.cpp
│ ├── SplayTreeReversable
│ ├── Sqrt
│ │ ├── MoWithUpdate.cpp
│ │ └── SqrtDecomposition.cpp
│ ├── SquareRootOptimization.cpp
│ ├── TreapSet.cpp
│ ├── Treap_SegmentTree.cpp
│ ├── UniqueTreeEncoding.cpp
│ └── WaveletTree.cpp
├── Utils
│ ├── Printer.cpp
│ ├── Random.cpp
│ └── SidePrinter.cpp
└── src
│ └── main.cpp
├── Images
└── Aho-Corasick
│ ├── AhoCorasick-Example.PNG
│ └── AhoCorasick-Example.gliffy
├── LICENSE
└── README.md
/Codes/.gitignore:
--------------------------------------------------------------------------------
1 | /Graph
2 | /Debug
3 |
--------------------------------------------------------------------------------
/Codes/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Codes
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 | ?name?
14 |
15 |
16 |
17 | org.eclipse.cdt.make.core.append_environment
18 | true
19 |
20 |
21 | org.eclipse.cdt.make.core.autoBuildTarget
22 | all
23 |
24 |
25 | org.eclipse.cdt.make.core.buildArguments
26 |
27 |
28 |
29 | org.eclipse.cdt.make.core.buildCommand
30 | make
31 |
32 |
33 | org.eclipse.cdt.make.core.buildLocation
34 | ${workspace_loc:/Codes/Debug}
35 |
36 |
37 | org.eclipse.cdt.make.core.cleanBuildTarget
38 | clean
39 |
40 |
41 | org.eclipse.cdt.make.core.contents
42 | org.eclipse.cdt.make.core.activeConfigSettings
43 |
44 |
45 | org.eclipse.cdt.make.core.enableAutoBuild
46 | false
47 |
48 |
49 | org.eclipse.cdt.make.core.enableCleanBuild
50 | true
51 |
52 |
53 | org.eclipse.cdt.make.core.enableFullBuild
54 | true
55 |
56 |
57 | org.eclipse.cdt.make.core.fullBuildTarget
58 | all
59 |
60 |
61 | org.eclipse.cdt.make.core.stopOnError
62 | true
63 |
64 |
65 | org.eclipse.cdt.make.core.useDefaultBuildCmd
66 | true
67 |
68 |
69 |
70 |
71 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
72 | full,incremental,
73 |
74 |
75 |
76 |
77 |
78 | org.eclipse.cdt.core.cnature
79 | org.eclipse.cdt.core.ccnature
80 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
81 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
82 |
83 |
84 |
--------------------------------------------------------------------------------
/Codes/CHIVO DELUXE EDITION (ACM_2012).pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cjtoribio/Algorithms/9e9609b12e47b8897f7026198f2e55ffc9f457f5/Codes/CHIVO DELUXE EDITION (ACM_2012).pdf
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/ConvexHullTrick.cpp:
--------------------------------------------------------------------------------
1 | // algorithms
2 | // vector
3 | struct ConvexHullTrick {
4 | struct Line {
5 | double m,b;
6 | Line(double m,double b):m(m),b(b){}
7 | double inter(const Line &L)const{
8 | return (L.b-b) / (m - L.m);
9 | }
10 | double eval(double x){
11 | return m*x + b;
12 | }
13 | };
14 | vector V;
15 | vector X;
16 | int C;
17 | ConvexHullTrick():C(0){ };
18 | void add(Line l){
19 | while(V.size() >= 2){
20 | if(V[V.size()-2].inter(l) < X.back()){
21 | V.pop_back();
22 | X.pop_back();
23 | } else break;
24 | }
25 | if(V.size() >= 1){
26 | X.push_back(V.back().inter(l));
27 | }
28 | V.push_back(l);
29 | C = min(C , (int)X.size());
30 | }
31 | double eval(double x){
32 | int p = lower_bound(X.begin(),X.end(), x) - X.begin();
33 | return V[p].eval(x);
34 | }
35 | // only if x are used in increasing order
36 | double evalConstant(double x){
37 | while(C < X.size() && x > X[C])C++;
38 | return V[C].eval(x);
39 | }
40 | };
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/ConvexHullTrickSet.cpp:
--------------------------------------------------------------------------------
1 | #define INF 1e200
2 | template
3 | struct ConvexHull {
4 | struct LineX {
5 | Curve l;
6 | long double x;
7 | bool operator<(const LineX &o) const {
8 | return (o.x == -INF || x == -INF) ? cmp()(l, o.l) : (x + 1e-9 < o.x);
9 | }
10 | };
11 | set S;
12 | template static T prev(T a) { a--; return a; }
13 | template static T next(T a) { a++; return a; }
14 | void addLine(Curve l) {
15 | auto it = S.lower_bound({l, -INF});
16 | if (it != S.end() && it->l.m == l.m) return;
17 | if (it != S.end() && it != S.begin() && l.pitty(prev(it)->l, it->l)) return;
18 | vector tr;
19 | if (it != S.begin())
20 | for (auto r = prev(it); r != S.begin() && r->l.pitty(prev(r)->l, l); --r) {
21 | tr.push_back(r->l);
22 | }
23 | if (it != S.begin() && prev(it) == S.begin() && prev(it)->l.m == l.m)
24 | tr.push_back(prev(it)->l);
25 | for (auto f = it; f != S.end() && next(f) != S.end() && f->l.pitty(l, next(f)->l); f++) {
26 | tr.push_back(f->l);
27 | }
28 | for (auto t : tr) S.erase({t, -INF});
29 | vector ta;
30 | auto pr = S.lower_bound({l, -INF});
31 | if (pr != S.begin()) { pr--; ta.push_back(pr->l), S.erase(pr); }
32 | safeAdd(l);
33 | if (ta.size()) safeAdd(ta[0]);
34 | }
35 | void safeAdd(Curve l) {
36 | auto it = S.lower_bound({l, -INF});
37 | S.insert({l, it == S.end() ? INF : l.xinter(it->l)});
38 | }
39 | long double getBest(long double x) {
40 | auto it = S.lower_bound({{0, 0}, x});
41 | return x * it->l.m + it->l.b;
42 | }
43 | };
44 | struct Curve {
45 | double m, b;
46 | long double pitty(Curve le, Curve ri) const {
47 | return ((b - le.b)*(le.m - ri.m) >= (ri.b - le.b)*(le.m - m));
48 | }
49 | long double xinter(Curve o) const {
50 | return 1.0L * (o.b - b) / (m - o.m);
51 | }
52 | };
53 | struct IncSlope {
54 | bool operator()(const Curve &a, const Curve &b) {
55 | return a.m != b.m ? a.m < b.m : a.b < b.b;
56 | }
57 | };
58 | struct DecSlope {
59 | bool operator()(const Curve &a, const Curve &b) {
60 | return a.m != b.m ? a.m > b.m : a.b > b.b;
61 | }
62 | };
63 |
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/ConvexHullTrickSet.cpp (Underwork):
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Author: Simon Lindholm
4 | * Date: 2017-04-20
5 | * License: CC0
6 | * Source: own work
7 | * Description: Container where you can add lines of the form kx+m, and query maximum values at points x.
8 | * Useful for dynamic programming.
9 | * Time: O(\log N)
10 | * Status: tested
11 | */
12 | #pragma once
13 |
14 | struct Line {
15 | mutable ll k, m, p;
16 | bool operator<(const Line& o) const { return k < o.k; }
17 | bool operator<(ll x) const { return p < x; }
18 | };
19 |
20 | struct LineContainer : multiset> {
21 | // (for doubles, use inf = 1/.0, div(a,b) = a/b)
22 | const ll inf = LLONG_MAX;
23 | ll div(ll a, ll b) { // floored division
24 | return a / b - ((a ^ b) < 0 && a % b); }
25 | bool isect(iterator x, iterator y) {
26 | if (y == end()) { x->p = inf; return false; }
27 | if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
28 | else x->p = div(y->m - x->m, x->k - y->k);
29 | return x->p >= y->p;
30 | }
31 | void add(ll k, ll m) {
32 | auto z = insert({k, m, 0}), y = z++, x = y;
33 | while (isect(y, z)) z = erase(z);
34 | if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
35 | while ((y = x) != begin() && (--x)->p >= y->p)
36 | isect(x, erase(y));
37 | }
38 | ll query(ll x) {
39 | assert(!empty());
40 | auto l = *lower_bound(x);
41 | return l.k * x + l.m;
42 | }
43 | };
44 |
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/DynamicConvexHullTrick.cpp:
--------------------------------------------------------------------------------
1 | struct Line { long double m, b; };
2 | template
3 | struct ConvexHull {
4 | vector> lines;
5 | cmp c;
6 | ConvexHull():lines(1) { }
7 | void addLine(Line line){
8 | lines[0].insert(lower_bound(lines[0].begin(), lines[0].end(), line, c), line);
9 | clean(lines[0]);
10 | for(int i = 0; i < lines.size(); ++i){
11 | if(lines[i].size() > (1< &row : lines){
27 | if(row.size() == 0)continue;
28 | int lo = 0, hi = row.size()-1, b = -1;
29 | while(lo <= hi){
30 | int mi = (lo + hi)/2;
31 | if(mi == 0 || 1.0*(row[mi-1].b-row[mi].b)/(row[mi].m-row[mi-1].m) <= x){
32 | b = mi;
33 | lo = mi+1;
34 | }else{
35 | hi = mi-1;
36 | }
37 | }
38 | if(!hasValue) r = row[b].m * x + row[b].b;
39 | else r = c.best(r, row[b].m * x + row[b].b);
40 | hasValue = 1;
41 | }
42 | return r;
43 | }
44 | static bool pitty(Line a, Line b, Line c){
45 | return ((b.b - a.b)*(a.m - c.m) >= (c.b - a.b)*(a.m - b.m));
46 | }
47 | vector join(const vector &a, const vector &b){
48 | vector nl; nl.resize(a.size() + b.size());
49 | merge(a.begin(), a.end(), b.begin(), b.end(), nl.begin(), c);
50 | clean(nl);
51 | return nl;
52 | }
53 | static void clean(vector &lines){
54 | vector nl;
55 | for(Line l : lines){
56 | while(nl.size() >= 2 && pitty(nl[nl.size()-2], nl.back(), l))
57 | nl.pop_back();
58 | if (nl.size() && nl.back().m == l.m) nl.pop_back();
59 | nl.push_back(l);
60 | }
61 | lines = nl;
62 | }
63 | };
64 | struct IncSlope {
65 | bool operator()(const Line &a, const Line &b) {
66 | return a.m != b.m ? a.m < b.m : a.b < b.b;
67 | }
68 | double best(double a, double b) const {
69 | return max(a, b);
70 | }
71 | };
72 | struct DecSlope {
73 | bool operator()(const Line &a, const Line &b) {
74 | return a.m != b.m ? a.m > b.m : a.b > b.b;
75 | }
76 | double best(double a, double b) const {
77 | return min(a, b);
78 | }
79 | };
80 |
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/Histogram.cpp:
--------------------------------------------------------------------------------
1 | pair histogram(vector H) {
2 | stack> STK; // pos, height
3 | int mA = -1;
4 | pair ANS;
5 | STK.push(PII(-1, 0));
6 | H.push_back(0);
7 | for (int i = 0; i < H.size(); ++i) {
8 | int h = H[i];
9 | while (STK.size() > 1 && STK.top().second >= h) {
10 | auto c = STK.top(); STK.pop();
11 | int st = STK.top().first + 1, en = i - 1;
12 | int area = c.second * (en - st + 1);
13 | if (area > mA) {
14 | ANS = PII(st, en);
15 | mA = area;
16 | }
17 | }
18 | STK.push(PII(i, H[i]));
19 | }
20 | return ANS;
21 | }
22 |
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/InversionCount.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 | struct InversionCount
5 | {
6 | typedef long long Long;
7 | static Long inversionCount(vector V)
8 | {
9 | int N = V.size();
10 | int arr[N];
11 | for(int i = 0; i < N; ++i)
12 | arr[i] = V[i];
13 | Long ret = 0;
14 | for(int i = 0; (1<
24 | static Long countInv(ITERATOR begin , ITERATOR end)
25 | {
26 | if(end - begin <= 1)return 0;
27 | int N = end - begin;
28 | vector tmp(N);
29 |
30 | int ia = 0 , ib = N/2 , idx = 0;
31 | Long ans = 0;
32 | while(ib < N)
33 | {
34 | while(ia < N/2 && *(begin+ia) > *(begin+ib)){
35 | tmp[idx++] = *(begin + ia);
36 | ia++;
37 | }
38 | ans += ia;
39 | tmp[idx++] = *(begin + ib);
40 | ib++;
41 | }
42 | while(ia < N/2){
43 | tmp[idx++] = *(begin + ia);
44 | ia++;
45 | }
46 | for(int i = 0; i < N; ++i)
47 | *(begin + i) = tmp[i];
48 | return ans;
49 | }
50 | };
51 |
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/LIS.cpp:
--------------------------------------------------------------------------------
1 | struct LIS
2 | {
3 | static vector PreviusNumberLIS(const vector &input)
4 | {
5 | int N = input.size();
6 | vector KTH;
7 | vector P(N);
8 | for(int i = 0; i < N; ++i)
9 | {
10 | int v = input[i];
11 | int p = lower_bound(KTH.begin(), KTH.end(),v) - KTH.begin();
12 | if(p == (int)KTH.size()) KTH.push_back(v);
13 | else KTH[p] = v;
14 | P[i] = p > 0 ? KTH[p-1] : -1000000000;
15 | }
16 | map M; M[-1000000000] = -1;
17 | for(int i = 0; i < P.size(); ++i)
18 | {
19 | P[i] = M[P[i]];
20 | M[input[i]] = i;
21 | }
22 | return P;
23 | }
24 | };
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/Partitions.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 | struct Partitions
5 | {
6 | const static int MOD = 1000000007;
7 | /**
8 | * It is known that MaxParts < SQRT(2*MaxSum) + 5 otherwise DP[MaxParts][MaxSum] = 0
9 | * parts from the theory of taking a PARTITION of size K parts with the
10 | * smallest partition of size X and then SUBTRACTING X from each partition
11 | * which is the same number of DP(PARTS-1 , SUM - X*PARTS)
12 | * then DP(PARTS,SUM) += DP(PARTS-1, SUM - X*PARTS ) FOR X = [1..SUM]
13 | */
14 | static vector< vector > IncreasingDistinctParts(int MaxParts,int MaxSum)
15 | {
16 | vector > mem(MaxParts+1 , vector(MaxSum+1));
17 | for(int i = 1; i <= MaxParts; ++i)
18 | {
19 | vector prev(MaxSum+1);
20 | for(int k = 1; k <= MaxSum; ++k)
21 | {
22 | prev[k] = mem[i-1][k];
23 | if(i == 1)
24 | mem[i][k] = 1;
25 | else if(k >= i)
26 | {
27 | mem[i][k] = prev[k-i];
28 | prev[k] += prev[k-i];
29 | if(prev[k] >= MOD)prev[k] -= MOD;
30 | }
31 | }
32 | }
33 | return mem;
34 | }
35 | /**
36 | * parts from the theory of taking a PARTITION of size K parts with the
37 | * smallest partition of size X and then SUBTRACTING X from each partition
38 | * which is the same number of DP(PARTS-1 , SUM - X*PARTS)
39 | * then DP(PARTS,SUM) += DP(PARTS-1, SUM - X*PARTS ) FOR X = [0..SUM]
40 | */
41 | static vector< vector > IncreasingParts(int MaxParts,int MaxSum)
42 | {
43 | vector > mem(MaxParts+1 , vector(MaxSum+1));
44 | for(int i = 1; i <= MaxParts; ++i)
45 | {
46 | vector prev(MaxSum+1);
47 | for(int k = 0; k <= MaxSum; ++k)
48 | {
49 | prev[k] = mem[i-1][k];
50 | if(i == 1)
51 | mem[i][k] = 1;
52 | else if(k >= i)
53 | {
54 | prev[k] += prev[k-i];
55 | if(prev[k] >= MOD)prev[k] -= MOD;
56 | mem[i][k] = prev[k];
57 | }
58 | }
59 | }
60 | return mem;
61 | }
62 | static vector< vector > PermutedDistinctParts(int MaxParts,int MaxSum)
63 | {
64 | vector > mem = IncreasingDistinctParts(MaxParts,MaxSum);
65 | int F = 1;
66 | for(int i = 1; i <= MaxParts; ++i)
67 | {
68 | F = (1LL * F * i) % MOD;
69 | for(int k = 0; k <= MaxSum; ++k)
70 | {
71 | mem[i][k] = (1LL * mem[i][k] * F) % MOD;
72 | }
73 | }
74 | return mem;
75 | }
76 | static vector< vector > PermutedParts(int MaxParts,int MaxSum)
77 | {
78 | vector > mem(MaxParts+1 , vector(MaxSum+1));
79 | for(int i = 1; i <= MaxParts; ++i)
80 | {
81 | vector prev(MaxSum+1);
82 | for(int k = 0; k <= MaxSum; ++k)
83 | {
84 | prev[k] = mem[i-1][k];
85 | if(i == 1)
86 | mem[i][k] = 1;
87 | else
88 | {
89 | if(k > 0)prev[k] += prev[k-1];
90 | if(prev[k] >= MOD)prev[k] -= MOD;
91 | mem[i][k] = prev[k];
92 | }
93 | }
94 | }
95 | return mem;
96 | }
97 | };
98 |
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/PersistentConvexHullTrick.cpp:
--------------------------------------------------------------------------------
1 | typedef long double Double;
2 | typedef long long Long;
3 | struct ConvexHullTrick {
4 | struct Line {
5 | Double m,b;
6 | Line(Double m,Double b):m(m),b(b){}
7 | Double inter(const Line &L)const{
8 | return (L.b-b) / (m - L.m);
9 | }
10 | Double eval(Double x){
11 | return m*x + b;
12 | }
13 | };
14 | struct Node {
15 | Line l = Line(1, 0);
16 | Double intWithPrev = -1e100;
17 | vector par;
18 | vector to;
19 | };
20 | vector nodes;
21 | ConvexHullTrick(){ };
22 | void add(Line l, int version = -1){
23 | int id = nodes.size();
24 | Node nn; nn.l = l;
25 | if(nodes.size() != 0) {
26 | int p = version == -1 ? nodes.size() -1 : version;
27 | for (int i = nodes[p].par.size(); i >= 0 && p != 0; --i) {
28 | if (nodes[p].par.size() <= i) continue;
29 | if (nodes[p].par[i] == 0) continue;
30 | int pp = nodes[p].par[i];
31 | int ppp = nodes[pp].par[0];
32 | if(nodes[ppp].l.inter(l) < nodes[pp].intWithPrev) {
33 | p = ppp;
34 | } else {
35 | break;
36 | }
37 | }
38 | while(p != 0) {
39 | int pp = nodes[p].par[0];
40 | if(nodes[pp].l.inter(l) < nodes[p].intWithPrev) {
41 | p = pp;
42 | } else {
43 | break;
44 | }
45 | }
46 | nodes[p].to.push_back(id);
47 | nn.par.push_back(p);
48 | nn.intWithPrev = nn.l.inter(nodes[p].l);
49 | for(int i = 0; i < nodes[ nn.par[i] ].par.size(); ++i) {
50 | int rp = nn.par[i];
51 | nn.par.push_back(nodes[rp].par[i]);
52 | }
53 | assert(nn.par.size() <= 20);
54 | }
55 | nodes.push_back(nn);
56 | }
57 | Double eval(Double x, int version = -1){
58 | int n = version == -1 ? nodes.size() - 1 : version;
59 | // while(nodes[n].intWithPrev > x)
60 | // n = nodes[n].par[0];
61 | for (int i = nodes[n].par.size(); i >= 0; --i) {
62 | if (nodes[n].par.size() <= i) continue;
63 | int p = nodes[n].par[i];
64 | if (x < nodes[p].intWithPrev) {
65 | n = p;
66 | }
67 | }
68 | if (x < nodes[n].intWithPrev) n = nodes[n].par[0];
69 | return nodes[n].l.eval(x);
70 | }
71 | void print(int n = 0, int lvl = 0) {
72 | cout << string(lvl * 3, ' ')<< n << " " << nodes[n].intWithPrev << endl;
73 | for(int v : nodes[n].to)
74 | print(v, lvl+1);
75 | }
76 | };
77 |
--------------------------------------------------------------------------------
/Codes/DynamicProgramming/SubsetSum.cpp:
--------------------------------------------------------------------------------
1 | typedef vector VI;
2 | typedef vector VVI;
3 | typedef long long Long;
4 | // http://codeforces.com/blog/entry/45223
5 | struct SubsetSum {
6 | int mb;
7 | VI A, B, F;
8 | SubsetSum(int mb):mb(mb), A(1<= 0; --i) {
34 | if( n & (1< V = {1, 3, 4 ,2, 1, 4, 2};
45 | for (int i = 0; i < V.size(); ++i) {
46 | S.addVal(V[i], 1);
47 | }
48 | S.build();
49 | for (int i = 0; i < V.size(); ++i) {
50 | cout << S.bestOr(V[i]) << " " << S.sumSubsets(V[i]) << " " << S.sumSupersets(V[i]) << endl;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Codes/Geometry/AngleBetweenVectors.cpp:
--------------------------------------------------------------------------------
1 | double angle(Point A, Point B){
2 | return B.rotate(-A.angle()).angle();
3 | }
--------------------------------------------------------------------------------
/Codes/Geometry/BestCurveBuffer.cpp:
--------------------------------------------------------------------------------
1 | typedef long double Double;
2 | struct Curve {
3 | Double a, b, c; // a*(x - b) + c
4 | long double eval(Double x) {
5 | return a*(x - b)*(x - b) + c;
6 | }
7 | vector allInter(Curve &o) {
8 | /* a0 * (x - b0)^2 + c0 = a1 * (x - b1)^2 + c1
9 | (a0-a1)*x^2 - 2*(b0*a0-b1*a1)*x + (b0*b0+c0-c1-b1*b1) = 0 */
10 | Double na = (a - o.a);
11 | Double nb = -2*(a*b - o.a*o.b);
12 | Double nc = (a*b*b + c - o.c - o.a*o.b*o.b);
13 | if (na == 0) return nb == 0 ? vector() : vector(1, -nc / nb);
14 | if (nb*nb - 4*na*nc < 0) return {};
15 | Double det = sqrt(nb*nb - 4*na*nc);
16 | vector R = { (-nb - det) / (2*na), (-nb + det) / (2*na) };
17 | if (R[0] > R[1]) swap(R[0], R[1]);
18 | return R;
19 | }
20 | };
21 |
22 | struct Buffer {
23 | #define INF 1e200
24 | #define EPS 1e-9
25 | struct CurveDominance {
26 | int id;
27 | Double st, en;
28 | };
29 | vector C;
30 | vector D;
31 | void add(Curve c) {
32 | int nid = C.size();
33 | C.push_back(c);
34 | vector ND;
35 | for (auto p : D) {
36 | auto inters = c.allInter(C[p.id]);
37 | inters.push_back(INF);
38 | Double px = -INF;
39 | for (Double x : inters) {
40 | if (c.eval(x-1) >= C[p.id].eval(x-1)) {
41 | Double st = max(p.st, px);
42 | Double en = min(p.en, x);
43 | if (st <= en) {
44 | ND.push_back({p.id, st, en});
45 | }
46 | }
47 | px = x;
48 | }
49 | }
50 | D.clear();
51 | Double px = -INF;
52 | for (int i = 0; i < ND.size(); ++i) {
53 | if (ND[i].st > px) {
54 | D.push_back({nid, px, ND[i].st});
55 | }
56 | D.push_back(ND[i]);
57 | px = ND[i].en;
58 | }
59 | if (ND.size() == 0 || ND.back().en < INF) {
60 | D.push_back({nid, px, INF});
61 | }
62 | }
63 | Double query(Double x) {
64 | int lo = 0, hi = (int)D.size() - 1, ret = -1;
65 | while (lo <= hi) {
66 | int mi = (lo + hi) / 2;
67 | if (D[mi].en < x) {
68 | lo = mi + 1;
69 | } else {
70 | hi = mi - 1;
71 | ret = mi;
72 | }
73 | }
74 | return ret == -1 ? INF : C[D[ret].id].eval(x);
75 | }
76 | #undef EPS
77 | #undef INF
78 | };
79 |
--------------------------------------------------------------------------------
/Codes/Geometry/ConvexHullUL.cpp:
--------------------------------------------------------------------------------
1 | vector GetHull(vector V, int upper, int allow180 = true){
2 | vector H;
3 | int sz = 0, sig = upper ? 1 : -1;
4 | double eps = allow180 ? 0 : 1e-9;
5 | for(Point p : V){
6 | while(H.size() >= 2 && sig * ((H[sz-1]-H[sz-2])^(p-H[sz-2])) + eps > 0){
7 | H.pop_back();
8 | sz--;
9 | }
10 | H.push_back(p);
11 | sz++;
12 | }
13 | return H;
14 | }
15 | vector ConvexHullUL(vector V, int allow180 = true){
16 | if(V.size() <= 1)return V;
17 | sort(V.begin(),V.end());
18 | vector U = GetHull(V,true, allow180);
19 | vector L = GetHull(V,false, allow180);
20 | for(int i = L.size() - 2; i >= 1; --i){
21 | U.push_back(L[i]);
22 | }
23 | return U;
24 | }
--------------------------------------------------------------------------------
/Codes/Geometry/Generic/InsideSimplePolygon.cpp:
--------------------------------------------------------------------------------
1 | // returns -1 (inside), 0 (border), 1 (outside)
2 | template
3 | int pointVsPolygon(const Point& point, const Polygon& poly) {
4 | int n = static_cast(poly.size()), windingNumber = 0;
5 | for (int i = 0; i < n; ++i) {
6 | if (point == poly[i])
7 | return 0;
8 | int j = next(i, n);
9 | if (poly[i].y == point.y && poly[j].y == point.y) {
10 | if (min(poly[i].x, poly[j].x) <= point.x && point.x <= max(poly[i].x, poly[j].x))
11 | return 0;
12 | } else {
13 | bool below = poly[i].y < point.y;
14 | if (below != (poly[j].y < point.y)) {
15 | auto orientation = (poly[j] - poly[i]) ^ (point - poly[i]);
16 | if (orientation == 0)
17 | return 0;
18 | if (below == (orientation > 0))
19 | windingNumber += below ? 1 : -1;
20 | }
21 | }
22 | }
23 | return windingNumber == 0 ? 1 : -1;
24 | }
25 |
--------------------------------------------------------------------------------
/Codes/Geometry/Generic/Line.cpp:
--------------------------------------------------------------------------------
1 | template
2 | struct Line {
3 | Point a, ab;
4 | Line() : a(), ab() {}
5 | Line(Point a, Point b, bool twoPoints = true) : a(a), ab(twoPoints ? b - a : b) {}
6 |
7 | Point b() const { return a + ab; }
8 | operator bool () const { return ab != Point(); }
9 | bool aligned(Point o)const{ return ((o - a)^(ab)) == 0; }
10 | };
11 |
12 | /// Method for line and segment intersection intersection
13 | enum EC { R, C, O }; // Ray, Closed, Open
14 | template
15 | bool check(EC t, F a, F b){
16 | if(t == EC::R) return true;
17 | if(t == EC::C) return a <= b;
18 | if(t == EC::O) return a < b;
19 | }
20 | template
21 | bool intersectLines(Line lhs, Line rhs, Point& res, bool deb = 0) {
22 | auto s = lhs.ab ^ rhs.ab;
23 | if (s == 0) return false;
24 | auto ls = (rhs.a - lhs.a) ^ rhs.ab;
25 | auto rs = (rhs.a - lhs.a) ^ lhs.ab;
26 | if (s < 0) s = -s, ls = -ls, rs = -rs;
27 | bool intersect = check(LA, decltype(ls)(0), ls) && check(LB, ls, s) &&
28 | check(RA, decltype(rs)(0), rs) && check(RB, rs, s);
29 | if (intersect) res = lhs.a + lhs.ab * static_cast(ls) / s;
30 | return intersect;
31 | }
32 |
--------------------------------------------------------------------------------
/Codes/Geometry/Generic/Point.cpp:
--------------------------------------------------------------------------------
1 | template
2 | struct Point {
3 | F x, y;
4 | Point() : x(0), y(0) {}
5 | Point(const F& x, const F& y) : x(x), y(y) {}
6 |
7 | template
8 | Point& operator = (const Point& o) { x = o.x; y = o.y; return *this; }
9 | template explicit operator Point () const {
10 | return Point(static_cast(x), static_cast(y)); }
11 |
12 | };
13 |
14 | template inline Point makePoint(const F& x, const F& y) { return Point(x, y); }
15 |
16 | #define FUNC1(name, arg, expr) \
17 | template inline auto name(const arg) -> decltype(expr) { return expr; }
18 | #define FUNC2(name, arg1, arg2, expr) \
19 | template \
20 | inline auto name(const arg1, const arg2) -> decltype(expr) { return expr; }
21 | #define FUNC3(name, arg1, arg2, arg3, expr) \
22 | template \
23 | inline auto name(const arg1, const arg2, const arg3) -> decltype(expr) { return expr; }
24 |
25 | FUNC1(operator -, Point& p, makePoint(-p.x, -p.y))
26 | FUNC1(gcd, Point& p, p / abs(__gcd(p.x, p.y)) )
27 | FUNC2(operator +, Point& lhs, Point& rhs, makePoint(lhs.x + rhs.x, lhs.y + rhs.y))
28 | FUNC2(operator -, Point& lhs, Point& rhs, makePoint(lhs.x - rhs.x, lhs.y - rhs.y))
29 | FUNC2(operator *, F1& factor, Point& rhs, makePoint(factor * rhs.x, factor * rhs.y))
30 | FUNC2(operator *, Point& lhs, F2& factor, makePoint(lhs.x * factor, lhs.y * factor))
31 | FUNC2(operator /, Point& lhs, F2& factor, makePoint(lhs.x / factor, lhs.y / factor))
32 | FUNC2(operator *, Point& lhs, Point& rhs, lhs.x * rhs.x + lhs.y * rhs.y)
33 | FUNC2(operator ^, Point& lhs, Point& rhs, lhs.x * rhs.y - lhs.y * rhs.x)
34 |
35 | FUNC2(operator ==, Point& lhs, Point& rhs, lhs.x == rhs.x && lhs.y == rhs.y)
36 | FUNC2(operator !=, Point& lhs, Point& rhs, !(lhs == rhs))
37 | FUNC2(operator <, Point& lhs, Point& rhs, lhs.x < rhs.x || (lhs.x == rhs.x && lhs.y < rhs.y))
38 |
39 | FUNC2(ccw, Point& lhs, Point& rhs, rhs ^ lhs)
40 | FUNC3(ccw, Point& lhs, Point& rhs, Point& origin, ccw(lhs - origin, rhs - origin))
41 |
42 | #undef FUNC1
43 | #undef FUNC2
44 | #undef FUNC3
45 |
46 | template ostream& operator << (ostream& os, const Point& point) { return os << point.x << ',' << point.y; }
47 |
--------------------------------------------------------------------------------
/Codes/Geometry/Generic/Polygon.cpp:
--------------------------------------------------------------------------------
1 | template using Polygon = vector>;
2 | inline int prev(int i, int n) { return i == 0 ? n-1 : i-1; }
3 | inline int next(int i, int n) { return i == n-1 ? 0 : i+1; }
4 | template inline int sgn(const T& x) { return (T(0) < x) - (x < T(0)); }
5 |
--------------------------------------------------------------------------------
/Codes/Geometry/Generic/VectorMethods.cpp:
--------------------------------------------------------------------------------
1 | /// validates if c is a vector inside the angle aToB inclusive,
2 | /// for exclusive remove the first line.
3 | template
4 | bool betweenAngle(Point a, Point b, Point c){
5 | if( ((a^c) == 0 && (a*c) > 0) || ((b^c) == 0 && (b*c) > 0) )return 1;
6 | if( (a^b) > 0 )return (a^c) > 0 && (c^b) > 0;
7 | if( (a^b) < 0 )
8 | return !((b^c) > 0 && (c^a) > 0);
9 | return a*b == 0 ? 0 : (a^c) > 0;
10 | }
11 |
--------------------------------------------------------------------------------
/Codes/Geometry/InsideConvex.cpp:
--------------------------------------------------------------------------------
1 | struct InsideConvexDetection {
2 | vector CH;
3 | vector A; // angles in increasing order [0,...
4 | Point center;
5 | // accept clockwise
6 | Wedge(vector _CH) : CH(_CH) {
7 | reverse(CH.begin(), CH.end());
8 | for (Point p : CH) {
9 | center = center + p;
10 | }
11 | center = center.scale(1.0 / CH.size());
12 | A.push_back(0);
13 | for (int i = 1; i < CH.size(); ++i) {
14 | A.push_back((CH[0] - center).angle(CH[i] - center));
15 | }
16 | }
17 | bool isIn(Point p) {
18 | Double ang = (CH[0] - center).angle(p - center);
19 | int pos = upper_bound(A.begin(), A.end(), ang) - A.begin();
20 | pos--;
21 | if (((CH[(pos + 1) % CH.size()] - CH[pos]) ^ (p - CH[pos])) < 0) {
22 | return false;
23 | }
24 | return true;
25 | }
26 | };
--------------------------------------------------------------------------------
/Codes/Geometry/PointStruct.cpp:
--------------------------------------------------------------------------------
1 | typedef long double Double;
2 | struct Point {
3 | Double x, y;
4 | Point(Double x = 0, Double y = 0) : x(x), y(y) {}
5 | Point round() const { return Point(round(x), round(y)); }
6 | Point operator-(const Point &P) const { return Point(x - P.x, y - P.y); }
7 | Point operator+(const Point &P) const { return Point(x + P.x, y + P.y); }
8 | Double operator^(const Point &P) { return x * P.y - y * P.x; }
9 | Double operator*(const Point &P) { return x * P.x + y * P.y; }
10 | Double sqMag() const { return x * x + y * y; }
11 | Double mag() const { return sqrt(sqMag()); }
12 | Point unit() const {
13 | Double m = mag();
14 | return Point(x / m, y / m);
15 | }
16 | Point scale(const Double &d) const { return Point(x * d, y * d); }
17 | Point rotate90() { return Point(-y, x); }
18 | Point rotate(const Double &a) const {
19 | return Point(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a));
20 | }
21 | bool operator<(const Point &p) const {
22 | return (x != p.x ? x < p.x : y < p.y);
23 | }
24 | bool operator==(const Point &P) const { return x == P.x && y == P.y; }
25 | bool similar(const Point &P) {
26 | Double rex = abs(x - P.x) / max(1.0L, abs(P.x));
27 | Double rey = abs(y - P.y) / max(1.0L, abs(P.y));
28 | return rex < 1e-12 && rey < 1e-12;
29 | }
30 | Double angle() const {
31 | Double an = atan2(y, x);
32 | if (an < 0) an += 2 * acos(-1);
33 | return an;
34 | }
35 | Double angle(const Point &p) const {
36 | return p.rotate(-angle()).angle();
37 | }
38 | Double smallAngle(const Point &p) const {
39 | Double ang = angle(p);
40 | if (ang > M_PI) return ang - 2 * M_PI;
41 | return ang;
42 | }
43 | int getSide(const Point &p){ // (< 0):left, (==0):aligned, (> 0):right
44 | return (*this)^(p);
45 | }
46 | static long long round(Double d) {
47 | if (d < 0) return (long long)(d - 0.5);
48 | return (long long)(d + 0.5);
49 | }
50 | };
51 | ostream& operator<<(ostream& o, const Point &P){
52 | return o <<"("<< P.x << "," << P.y << ")";
53 | }
--------------------------------------------------------------------------------
/Codes/Geometry/PointToPolygonProjector.cpp:
--------------------------------------------------------------------------------
1 | struct PointToPolygonProjector {
2 | vector CH; // convex-hull clockwise
3 | Point center;
4 | PointToPolygonProjector(vector _CH) : CH(_CH), center(0, 0) {
5 | for (Point &p : CH) {
6 | center = center + p;
7 | }
8 | center = center.scale(1.0 / CH.size());
9 | }
10 | pair getWindow(Point p) {
11 | int ff = lowerBoundAngle(p, 0);
12 | int fs = lowerBoundAngle(p, M_PI) - 1;
13 | if (fs < 0) fs += CH.size();
14 | int sf = (CH.size() + ff - 1) % CH.size();
15 | int ss = (fs + 1) % CH.size();
16 | return make_pair(bestAngle(p, ss, sf, -1), bestAngle(p, ff, fs, 1));
17 | }
18 | int bestAngle(Point p, int lo, int hi, int sig = 1) {
19 | // int sig = (center - p).getSide(CH[lo] - p) < 0 ? -1 : 1;
20 | int N = CH.size();
21 | if (hi < lo) hi += N;
22 | while (hi - lo > 2) {
23 | int mi1 = lo + 1 * (hi - lo) / 3;
24 | int mi2 = lo + 2 * (hi - lo) / 3;
25 | if ((CH[mi1%N] - p).getSide(CH[mi2%N] - p) * sig > 0) {
26 | lo = mi1;
27 | } else {
28 | hi = mi2;
29 | }
30 | }
31 | int b = lo;
32 | for (int i = lo; i <= hi; ++i) {
33 | if ((CH[b%N] - p).getSide(CH[i%N] - p) * sig > 0) {
34 | b = i;
35 | }
36 | }
37 | return b % N;
38 | }
39 | Double getAngle(Point f, Point s) {
40 | return (f - center).angle(s - center);
41 | }
42 | int lowerBoundAngle(Point p, Double target) {
43 | Double ang = getAngle(CH[0], p);
44 | // Double ang = getAngle(AN[0], ref);
45 | if (target < ang) target += 2 * M_PI;
46 | int N = CH.size();
47 | int lo = 0, hi = N;
48 | while (lo < hi) {
49 | int mi = (lo + hi) / 2;
50 | Double e = getAngle(CH[mi], p);
51 | if (e < ang) e += 2 * M_PI;
52 | if (e < target)
53 | lo = mi + 1;
54 | else
55 | hi = mi;
56 | }
57 | lo %= N;
58 | return lo;
59 | }
60 | };
--------------------------------------------------------------------------------
/Codes/Geometry/SegmentIntercect.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | (A-C + (B-A)*t) ^ (D-C) = 0
3 | (B-A -> m : D-C -> n)
4 | (a.x + t*m.x)*n.y - (a.y + t*m.y)*n.x = 0
5 | a.x*n.y - a.y*n.x + t*(m^n) = 0
6 | t*(m^n) = n^a
7 | t = - ((a-c)^n) / (m^n)
8 | */
9 | Point segIntercept(const Point &A, const Point &B, const Point &C, const Point &D){
10 | Point m = (B-A);
11 | Point n = (D-C);
12 | Double t = - ((A-C)^n) / (m^n);
13 | return A + m.scale(t);
14 | }
15 | bool hasIntercept(const Point &A, const Point &B, const Point &C, const Point &D){
16 | Point m = (B-A);
17 | Point n = (D-C);
18 | if(Point::similar(m^n, 0))return false; // parallel
19 | double t = - ((A-C)^n) / (m^n);
20 | return 0-1e9 <= t && t <= 1+1e9; // lies between
21 | }
--------------------------------------------------------------------------------
/Codes/Geometry/ThirdPointLeft.cpp:
--------------------------------------------------------------------------------
1 | Point thirdPointLeft(Point A,Point B, Double ac, Double bc){
2 | Point AB = B-A;
3 | Double ab = AB.mag();
4 | Double s = (ac+ab+bc)/2;
5 | // assert(s > ac && s > ab && s > bc);
6 | Double area = sqrt(s*(s-ab))*sqrt((s-bc)*(s-ac));
7 | Double h = 2*area / ab;
8 | Double ax = sqrt(ac*ac - h*h);
9 | Double bx = sqrt(bc*bc - h*h);
10 | if(ax > bx){
11 | return A + AB.unit().scale(ax) + AB.unit().rotate90().scale(h);
12 | }else{
13 | return B + AB.unit().scale(-bx) + AB.unit().rotate90().scale(h);
14 | }
15 | }
--------------------------------------------------------------------------------
/Codes/Graph/2-SAT.cpp:
--------------------------------------------------------------------------------
1 | // SOURCE: https://sites.google.com/site/indy256/algo/2_sat
2 | typedef vector VI;
3 | typedef vector VVI;
4 | struct SAT2
5 | {
6 | VVI adj , radj;
7 | VI vis , order, comp , sat;
8 | SAT2(int N){
9 | adj = VVI(2*(N+1));
10 | radj = VVI(2*(N+1));
11 | }
12 | void addImplication(int i,int j)
13 | {
14 | int si = i < 0 ? 1 : 0;
15 | int sj = j < 0 ? 1 : 0;
16 | i = abs(i); j = abs(j);
17 | adj[2*i+si].push_back(2*j+sj);
18 | radj[2*j+sj].push_back(2*i+si);
19 | adj[2*j+!sj].push_back(2*j+!sj);
20 | radj[2*i+!sj].push_back(2*j+!si);
21 | }
22 | void addOr(int i, int j){
23 | addImplication(-i, j);
24 | addImplication(-j, i);
25 | }
26 | void addXor(int i, int j){
27 | addImplication(i, -j);
28 | addImplication(j, -i);
29 | addImplication(-i, j);
30 | addImplication(-j, i);
31 | }
32 | void setTrue(int i){
33 | addImplication(-i, i);
34 | }
35 | void dfs1(int u)
36 | {
37 | vis[u] = 1;
38 | for(int i = 0; i < adj[u].size(); ++i)
39 | {
40 | int v = adj[u][i];
41 | if(!vis[v]) dfs1(v);
42 | }
43 | order.push_back(u);
44 | }
45 | void dfs2(int u,int color)
46 | {
47 | comp[u] = color;
48 | for(int i = 0; i < radj[u].size(); ++i)
49 | {
50 | int v = radj[u][i];
51 | if(comp[v] == -1)
52 | dfs2(v,color);
53 | }
54 | }
55 | bool run2SAT()
56 | {
57 | int N = adj.size();
58 | vis = VI(N);
59 | comp = VI(N,-1);
60 | sat = VI(N / 2);
61 | for(int i = 0; i < N; ++i)
62 | if(!vis[i])
63 | dfs1(i);
64 | int c = 0;
65 | for(int i = 0; i < N; ++i)
66 | {
67 | int u = order[N-i-1];
68 | if(comp[u] == -1)
69 | dfs2(u,c++);
70 | }
71 | for(int i = 0; i < N; i++)
72 | if(comp[i] == comp[i^1])
73 | return false;
74 | for (int i = 0; i < N; i += 2)
75 | {
76 | sat[i / 2] = comp[i] > comp[i ^ 1];
77 | // cout << i/2 << " " << (sat[i/2]?"true":"false") << endl;
78 | }
79 | return true;
80 | }
81 | };
82 |
--------------------------------------------------------------------------------
/Codes/Graph/CountMinimumSpanningTree.cpp:
--------------------------------------------------------------------------------
1 | struct CountMST{
2 | struct Edge {
3 | int u,v,w;
4 | bool operator<(const Edge &C)const{
5 | return w < C.w;
6 | }
7 | };
8 | int N;
9 | vector E;
10 | CountMST(int N):N(N){ }
11 | void addEdge(int u,int v,int w){
12 | E.push_back((Edge){u,v,w});
13 | }
14 | mint countMST(){
15 | sort(E.begin(),E.end());
16 | // exists MST
17 | {
18 | DisjointSet DS(N);
19 | for(Edge &e : E){
20 | DS.join(e.u, e.v);
21 | }
22 | if(DS.size() > 1){
23 | return 0;
24 | }
25 | }
26 |
27 | mint r = 1;
28 | // count
29 | {
30 | DisjointSet DS(N);
31 | for(int i = 0; i < E.size(); ){
32 | vector S;
33 | {// put equal edges
34 | int j = i;
35 | while(j < E.size() && E[i].w == E[j].w){
36 | S.push_back(E[j]);
37 | j++;
38 | }
39 | i = j;
40 | }
41 | for(Edge &e : S){
42 | e.u = DS.find(e.u);
43 | e.v = DS.find(e.v);
44 | }
45 | for(Edge &e : S){
46 | DS.join(e.u, e.v);
47 | }
48 | vector< pair > G;
49 | for(Edge &e : S){
50 | if(e.u != e.v){
51 | G.push_back(make_pair(DS.find(e.u), e));
52 | }
53 | }
54 | sort(G.begin(),G.end());
55 | for(int j = 0; j < G.size(); ){
56 | vector ee;
57 | {// put all same node
58 | int k = j;
59 | while(k < G.size() && G[k].first == G[j].first){
60 | ee.push_back(G[k].second);
61 | k++;
62 | }
63 | j = k;
64 | }
65 | vector NODS;
66 | for(Edge &e : ee){
67 | NODS.push_back(e.u);
68 | NODS.push_back(e.v);
69 | }
70 | sort(NODS.begin(),NODS.end());
71 | NODS.resize(unique(NODS.begin(),NODS.end())- NODS.begin());
72 | CountSpanningTree CS(NODS.size());
73 | for(Edge &e : ee){
74 | int u = lower_bound(NODS.begin(),NODS.end(),e.u)-NODS.begin();
75 | int v = lower_bound(NODS.begin(),NODS.end(),e.v)-NODS.begin();
76 | CS.addEdge(u,v);
77 | }
78 | r = r * CS.run();
79 |
80 | }
81 |
82 | }
83 | }
84 | return r;
85 | }
86 | };
--------------------------------------------------------------------------------
/Codes/Graph/CountSpanningTree.cpp:
--------------------------------------------------------------------------------
1 | struct CountSpanningTree {
2 | typedef vector VM;
3 | typedef vector VVM;
4 | VVM mat;
5 | int N;
6 | CountSpanningTree(int N):N(N){
7 | mat = VVM(N, VM(N));
8 | }
9 | void addEdge(int u, int v){
10 | mat[u][u] += 1;
11 | mat[v][v] += 1;
12 | mat[u][v] -= 1;
13 | mat[v][u] -= 1;
14 | }
15 | mint run(){
16 | for(int i = 0; i < N; ++i){
17 | for(int j = i+1; j < N; ++j){
18 | if(mat[i][i].n == 0)return 0;
19 | mint F = mat[j][i] / mat[i][i];
20 | for(int k = 0; k < N; ++k){
21 | mat[j][k] -= mat[i][k] * F;
22 | }
23 | }
24 | }
25 | mint r = 1;
26 | for(int i = 0; i < N-1; ++i){
27 | r = r * mat[i][i];
28 | }
29 | if(mat[N-1][N-1].n != 0)assert(false);
30 | return r;
31 | }
32 | };
--------------------------------------------------------------------------------
/Codes/Graph/EulerianPathAndCycle.cpp:
--------------------------------------------------------------------------------
1 | typedef vector VI;
2 | typedef vector VVI;
3 | struct EulerianPath {
4 | struct Edge{
5 | int u,v,used;
6 | int getV(int _u){
7 | return _u == u ? v : u;
8 | }
9 | };
10 | bool directed;
11 | VVI adj;
12 | vector E;
13 | VI cId, outDeg, inDeg;
14 | int N;
15 | EulerianPath(int N, int directed = false){
16 | this->directed = directed;
17 | this->N = N;
18 | adj = VVI(N);
19 | cId = VI(N);
20 | outDeg= VI(N);
21 | inDeg = VI(N);
22 | }
23 | void addEdge(int u,int v){
24 | Edge e = (Edge){ u, v, 0 };
25 | adj[u].push_back(E.size());
26 | outDeg[u]++;
27 | inDeg[v]++;
28 | if(!directed){
29 | adj[v].push_back(E.size());
30 | outDeg[v]++;
31 | inDeg[u]++;
32 | }
33 | E.push_back(e);
34 | }
35 | vector getEulerPath(){
36 | int st = -1 , cnt = 0;
37 | for(int i = 0; i < N; ++i){
38 | if(st == -1 && outDeg[i])
39 | st = i;
40 | if(directed){
41 | int d = outDeg[i] - inDeg[i];
42 | if(d > 1)return vector();
43 | if(d ==1)st = i, cnt++;
44 | if(cnt>=2)return vector();
45 | }else{
46 | int d = outDeg[i];
47 | if(d%2!=0)st = i, cnt++;
48 | if(cnt> 2)return vector();
49 | }
50 | }
51 | stack STK;
52 | STK.push(st);
53 | vector ret;
54 | while(STK.size()){
55 | int u = STK.top();
56 | bool found = false;
57 | while(cId[u] < adj[u].size()){
58 | Edge &e = E[adj[u][cId[u]++]];
59 | if(e.used)continue;
60 | e.used = true;
61 | int v = e.getV(u);
62 | found = true;
63 | STK.push(v);
64 | break;
65 | }
66 | if(!found){
67 | STK.pop();
68 | ret.push_back(u);
69 | }
70 | }
71 | reverse(ret.begin(),ret.end());
72 | return ret;
73 | }
74 | };
75 |
--------------------------------------------------------------------------------
/Codes/Graph/Flow/MinCostMaxFlow[AdjList].cpp:
--------------------------------------------------------------------------------
1 | typedef long long Long;
2 | const Long INF = 1000000000000000000LL;
3 | struct Edge { int to, cap, cost, flow, back; };
4 | struct MinCostFlow {
5 | int n;
6 | vector> g;
7 | MinCostFlow(int n):n(n), g(n) {}
8 | void add_rib(int a, int b, int u, int c) {
9 | Edge r1 = {b, u, c, 0, g[b].size()};
10 | Edge r2 = {a, 0, -c, 0, g[a].size()};
11 | g[a].push_back(r1);
12 | g[b].push_back(r2);
13 | }
14 | pair run(int s, int t, Long k = 1000000000000000000LL) {
15 | Long flow = 0, cost = 0;
16 | while (flow < k) {
17 | vector id(n, 0);
18 | vector d(n, INF);
19 | vector q(n);
20 | vector p(n);
21 | vector p_rib(n);
22 | int qh = 0, qt = 0;
23 | q[qt++] = s;
24 | d[s] = 0;
25 | while (qh != qt) {
26 | int v = q[qh++];
27 | id[v] = 2;
28 | if (qh == n) qh = 0;
29 | for (int i = 0; i < g[v].size(); ++i) {
30 | Edge &r = g[v][i];
31 | if (r.flow < r.cap && d[v] + r.cost < d[r.to]) {
32 | d[r.to] = d[v] + r.cost;
33 | if (id[r.to] == 0) {
34 | q[qt++] = r.to;
35 | if (qt == n) qt = 0;
36 | } else if (id[r.to] == 2) {
37 | if (--qh == -1) qh = n - 1;
38 | q[qh] = r.to;
39 | }
40 | id[r.to] = 1;
41 | p[r.to] = v;
42 | p_rib[r.to] = i;
43 | }
44 | }
45 | }
46 | if (d[t] == INF) break;
47 | Long addflow = k - flow;
48 | for (int v = t; v != s; v = p[v]) {
49 | Edge &f = g[p[v]][p_rib[v]];
50 | addflow = min(addflow, (Long) f.cap - f.flow);
51 | }
52 | for (int v = t; v != s; v = p[v]) {
53 | Edge &f = g[p[v]][p_rib[v]]; // forward edge
54 | Edge &b = g[v][f.back]; // backward edge
55 | f.flow += addflow; b.flow -= addflow;
56 | cost += f.cost * addflow;
57 | }
58 | flow += addflow;
59 | }
60 | return make_pair(flow, cost);
61 | }
62 | };
63 |
--------------------------------------------------------------------------------
/Codes/Graph/HopcroftCarp.cpp:
--------------------------------------------------------------------------------
1 | #define MAX 100001
2 | #define NIL 0
3 | #define INF (1<<28)
4 |
5 | vector< int > G[MAX];
6 | int n, m, match[MAX], dist[MAX];
7 | // n: number of nodes on left side, nodes are numbered 1 to n
8 | // m: number of nodes on right side, nodes are numbered n+1 to n+m
9 | // G = NIL[0] ∪ G1[G[1---n]] ∪ G2[G[n+1---n+m]]
10 |
11 | bool bfs() {
12 | int i, u, v, len;
13 | queue< int > Q;
14 | for(i=1; i<=n; i++) {
15 | if(match[i]==NIL) {
16 | dist[i] = 0;
17 | Q.push(i);
18 | }
19 | else dist[i] = INF;
20 | }
21 | dist[NIL] = INF;
22 | while(!Q.empty()) {
23 | u = Q.front(); Q.pop();
24 | if(u!=NIL) {
25 | len = G[u].size();
26 | for(i=0; i u(n + 1), v(m + 1), p(m + 1), way(m + 1);
8 | for (int i = 1; i <= n; ++i) {
9 | p[0] = i;
10 | int j0 = 0;
11 | vector minv(m + 1, INF);
12 | vector used(m + 1, false);
13 | do {
14 | used[j0] = true;
15 | int i0 = p[j0], delta = INF, j1;
16 | for (int j = 1; j <= m; ++j)
17 | if (!used[j]) {
18 | int cur = a[i0 - 1][j - 1] - u[i0] - v[j];
19 | if (cur < minv[j])
20 | minv[j] = cur, way[j] = j0;
21 | if (minv[j] < delta)
22 | delta = minv[j], j1 = j;
23 | }
24 | for (int j = 0; j <= m; ++j)
25 | if (used[j])
26 | u[p[j]] += delta, v[j] -= delta;
27 | else
28 | minv[j] -= delta;
29 | j0 = j1;
30 | } while (p[j0] != 0);
31 | do {
32 | int j1 = way[j0];
33 | p[j0] = p[j1];
34 | j0 = j1;
35 | } while (j0);
36 | }
37 | matchL = VI(n, -1), matchR = VI(m);
38 | for (int j = 1; j <= m; ++j) if (p[j]) matchL[p[j] - 1] = j - 1;
39 | for (int j = 1; j <= m; ++j) matchR[j - 1] = p[j] - 1;
40 | return cost = -v[0];
41 | }
42 | };
--------------------------------------------------------------------------------
/Codes/Graph/MaxFlow[Dinics-EdgeList].cpp:
--------------------------------------------------------------------------------
1 | // Adjacency list implementation of Dinic's blocking flow algorithm.
2 | // This is very fast in practice, and only loses to push-relabel flow.
3 | //
4 | // Running time:
5 | // O(|V|^2 |E|)
6 | //
7 | // INPUT:
8 | // - graph, constructed using AddEdge()
9 | // - source
10 | // - sink
11 | //
12 | // OUTPUT:
13 | // - maximum flow value
14 | // - To obtain the actual flow values, look at all edges with
15 | // capacity > 0 (zero capacity edges are residual edges).
16 | // SOURCE:
17 | // - http://www.stanford.edu/~liszt90/acm/notebook.html#file1
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | using namespace std;
25 |
26 | const int INF = 2000000000;
27 |
28 | struct Edge {
29 | int from, to, cap, flow, index;
30 | Edge(int from, int to, int cap, int flow, int index) :
31 | from(from), to(to), cap(cap), flow(flow), index(index) {}
32 | };
33 |
34 | struct Dinic {
35 | int N;
36 | vector > G;
37 | vector dad;
38 | vector Q;
39 |
40 | Dinic(int N) : N(N), G(N), dad(N), Q(N) {}
41 |
42 | void AddEdge(int from, int to, int cap) {
43 | G[from].push_back(Edge(from, to, cap, 0, G[to].size()));
44 | if (from == to) G[from].back().index++;
45 | G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
46 | }
47 |
48 | long long BlockingFlow(int s, int t) {
49 | fill(dad.begin(), dad.end(), (Edge *) NULL);
50 | dad[s] = &G[0][0] - 1;
51 |
52 | int head = 0, tail = 0;
53 | Q[tail++] = s;
54 | while (head < tail) {
55 | int x = Q[head++];
56 | for (int i = 0; i < G[x].size(); i++) {
57 | Edge &e = G[x][i];
58 | if (!dad[e.to] && e.cap - e.flow > 0) {
59 | dad[e.to] = &G[x][i];
60 | Q[tail++] = e.to;
61 | }
62 | }
63 | }
64 | if (!dad[t]) return 0;
65 |
66 | long long totflow = 0;
67 | for (int i = 0; i < G[t].size(); i++) {
68 | Edge *start = &G[G[t][i].to][G[t][i].index];
69 | int amt = INF;
70 | for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
71 | if (!e) { amt = 0; break; }
72 | amt = min(amt, e->cap - e->flow);
73 | }
74 | if (amt == 0) continue;
75 | for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
76 | e->flow += amt;
77 | G[e->to][e->index].flow -= amt;
78 | }
79 | totflow += amt;
80 | }
81 | return totflow;
82 | }
83 |
84 | long long GetMaxFlow(int s, int t) {
85 | long long totflow = 0;
86 | while (long long flow = BlockingFlow(s, t))
87 | totflow += flow;
88 | return totflow;
89 | }
90 | };
91 |
92 | //int main()
93 | //{
94 | // cin.sync_with_stdio(false);
95 | //
96 | //
97 | //
98 | //
99 | //
100 | //
101 | // return 0;
102 | //}
103 |
104 |
105 |
--------------------------------------------------------------------------------
/Codes/Graph/MaximumMatching.cpp:
--------------------------------------------------------------------------------
1 | struct MaxMatching {
2 | int L, R;
3 | vector ML, MR;
4 | VVI adj;
5 | MaxMatching(int L,int R) : ML(L,-1), MR(R,-1), adj(L), L(L), R(R) {}
6 | void AddEdge(int u, int v){
7 | adj[u].push_back(v);
8 | }
9 | int findMatch(int u, VI &VIS) {
10 | if (VIS[u]) return 0;
11 | VIS[u] = 1;
12 | for (int v : adj[u]) {
13 | if (MR[v] == -1 || findMatch(MR[v], VIS)) {
14 | MR[v] = u;
15 | ML[u] = v;
16 | return 1;
17 | }
18 | }
19 | return 0;
20 | }
21 | int run() {
22 | VI VIS(L);
23 | int cnt = 0;
24 | for (int i = 0; i < L; ++i) {
25 | VIS = VI(L);
26 | cnt += findMatch(i, VIS);
27 | }
28 | return cnt;
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/Codes/Graph/NOT_WORKING_MincostMaxflow[AdjMatrix].cpp:
--------------------------------------------------------------------------------
1 | // SOURCE:
2 | // - http://www.stanford.edu/~liszt90/acm/notebook.html#file2
3 | // - http://ideone.com/h1p9o4
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | using namespace std;
10 |
11 | typedef long long Long;
12 | typedef vector VL;
13 | typedef vector VVL;
14 | typedef vector VPII;
15 | const Long INF = numeric_limits::max() / 4;
16 | struct MinCostMaxFlow {
17 | int N;
18 | VVL cap, flow, cost;
19 | VL dist, pi, width , found;
20 | VPII P;
21 | MinCostMaxFlow(int N) {
22 | this->N = N;
23 | cap = flow = cost= VVL(N,VL(N));
24 | found = dist = pi = width = VL(N);
25 | P = VPII(N);
26 | }
27 | void AddEdge(int from, int to, Long cap, Long cost) {
28 | this->cap[from][to] = cap;
29 | this->cost[from][to] = cost;
30 | }
31 | Long Dijkstra(int s, int t) {
32 | fill(found.begin(), found.end(), false);
33 | fill(dist.begin(), dist.end(), INF);
34 | fill(width.begin(), width.end(), 0);
35 | dist[s] = 0;
36 | width[s] = INF;
37 | priority_queue PQ;
38 | PQ.push(PII(0, s));
39 | while (PQ.size()) {
40 | int u = PQ.top().second;
41 | PQ.pop();
42 | if (found[u]) continue;
43 | found[u] = true;
44 | for (int k = 0; k < N; k++) {
45 | if (found[k]) continue;
46 | int ca, nd;
47 | ca = cap[u][k] - flow[u][k], nd = dist[u] + pi[u] - pi[k] + cost[u][k];
48 | if (ca && nd < dist[k])
49 | dist[k] = nd, width[k] = ca, PQ.push(PII(-nd, k)), P[k] = PII(u, 1);
50 | ca = -flow[k][u], nd = dist[u] + pi[u] - pi[k] - cost[k][u];
51 | if (ca && nd < dist[k])
52 | dist[k] = nd, width[k] = ca, PQ.push(PII(-nd, k)), P[k] = PII(u, -1);
53 | }
54 | }
55 | for (int k = 0; k < N; k++)
56 | pi[k] = min(pi[k] + dist[k], INF);
57 | return width[t];
58 | }
59 | pair GetMaxFlow(int s, int t) {
60 | Long totflow = 0, totcost = 0;
61 | while (Long amt = Dijkstra(s, t)) {
62 | totflow += amt;
63 | for (int x = t; x != s; x = P[x].first) {
64 | int d = P[x].second , u = P[x].first , v = x;
65 | if(d==-1)swap(u,v);
66 | flow[u][v] += amt * d;
67 | totcost += amt * cost[u][v] * d;
68 | }
69 | }
70 | return make_pair(totflow, totcost);
71 | }
72 | };
73 |
--------------------------------------------------------------------------------
/Codes/Graph/README.md:
--------------------------------------------------------------------------------
1 | # Graph
2 | ## [2-SAT](./Codes/Graph/2-SAT.cpp):
3 | * 1-based implementation of 2-Satisfiability Problem (positive numbers for positive propositions and negative number for negative propositions.
4 |
5 | ## [Connected Components](/Codes/Graph/ConnectedComponnents.cpp)
6 | * Note: Need to extract necesary code for each of the following subproblems.
7 | * StronglyConnectedComponents
8 | * BiconnectedComponents
9 | * ArticulationPointsAndBridges
10 |
11 | ## [Count Number of Minimum Spanning Trees](/Codes/Graph/CountMinimumSpanningTree.cpp)
12 | * This is uses Count Number of Spanning Trees and [mint](/Codes/Math/ModInt.cpp#L68)
13 |
14 | ## [Count Number of Spanning Trees](/Codes/Graph/CountSpanningTree.cpp)
15 | * Note: Code is equivalent to building the matrix with addEdge and finding determinant. [mint](/Codes/Math/ModInt.cpp#L68) is just a ModularInt with the defined operations (/, *, +, -) [note modular division needed]
16 |
17 | ## [Eulerian Path And Cycle](/Codes/Graph/EulerianPathAndCycle)
18 | * Finds an eulerian path or a cycle in O(N)
19 |
20 | ## [HopcroftCarp](/Codes/Graph/EulerianPathAndCycle)
21 | * Maximum matching O(sqrt(V)*E)
22 |
23 | ## [Hungarian Algorithm](/Graph/MaxFlow%5BDinics-EdgeList%5D.cpp)
24 | * Finds a weighted maximum matching in O(V^3) best for dense graphs, for non complete graphs use INF as edge cost, an alternative is to run MinCostMaxFlow.
25 |
26 | ## [MaxFlow](/Codes/Graph/MincostMaxflow%5BAdjMatrix%5D.cpp)
27 | * Has a running time of O(|V|^2 |E|).
28 | * Can be used to find MaximumMatching and runs relatively fast, in theory same complexity as HopcroftCarp if all edges has capacity 1.
29 |
30 | ## [MinCostMaxFlow](/Codes/Graph/MincostMaxflow%5BAdjMatrix%5D.cpp)
31 | * Can be a substitute of HungarianAlgorithm and also other MaxFlow with costs involved.
32 |
33 | ## [VertextCover](/Codes/Graph/VertexCover.cpp)
34 | * Can find a minimum vertex cover after a maximum matching is provided.
35 | * NOTE: It does not have MaxMatching you have to run MaxMatching and then pass the matching to this algorithm.
36 |
--------------------------------------------------------------------------------
/Codes/Graph/VertexCover.cpp:
--------------------------------------------------------------------------------
1 | typedef vector VI;
2 | typedef vector VVI;
3 | struct Konig {
4 | vector ML, MR;
5 | VVI adj;
6 | int L,R, mm;
7 | Konig(int L,int R) : ML(L,-1), MR(R,-1), adj(L), L(L), R(R), mc(0) {}
8 | void AddEdge(int u, int v){
9 | adj[u].push_back(v);
10 | }
11 | void setMatch(int u, int v){
12 | ML[u] = v;
13 | MR[v] = u;
14 | mm++;
15 | }
16 | pair< vector , vector > getCover() {
17 | queue QL;
18 | vector VIS_L(L), VIS_R(R);
19 | for(int i = 0; i < L; ++i){
20 | if(ML[i] == -1){
21 | QL.push(i);
22 | VIS_L[i] = 1;
23 | }
24 | }
25 | while(QL.size()){
26 | int u = QL.front(); QL.pop();
27 | for(int i = 0; i < adj[u].size(); ++i){
28 | int v = adj[u][i];
29 | VIS_R[v] = 1;
30 | if(MR[v] != -1 && !VIS_L[ MR[v] ]) {
31 | VIS_L[MR[v]] = 1;
32 | QL.push(MR[v]);
33 | }
34 | }
35 | }
36 | vector AL, AR;
37 | for(int i = 0; i < L; ++i)
38 | if(!VIS_L[i]) AL.push_back(i);
39 | for(int i = 0; i < R; ++i)
40 | if(VIS_R[i]) AR.push_back(i);
41 | assert(mm == AL.size() + AR.size());
42 | return make_pair(AL,AR);
43 | }
44 | };
45 |
--------------------------------------------------------------------------------
/Codes/Math/BigPrimes.cpp:
--------------------------------------------------------------------------------
1 | namespace BigPrimes {
2 | typedef long long ll;
3 | ll gcd(ll a, ll b) {
4 | return a ? gcd(b % a, a) : b;
5 | }
6 |
7 | ll mulmod(ll a, ll b, ll c) { //returns (a*b)%c, and minimize overfloor
8 | return ((__int128_t ) a * b) % c;
9 | ll x = 0, y = a % c;
10 | while (b > 0) {
11 | if (b % 2 == 1)
12 | x = (x + y) % c;
13 | y = (y * 2) % c;
14 | b /= 2;
15 | }
16 | return x % c;
17 | }
18 |
19 | ll expmod(ll b, ll e, ll m) { //O(log b)
20 | if (!e)
21 | return 1;
22 | ll q = expmod(b, e / 2, m);
23 | q = mulmod(q, q, m);
24 | return e % 2 ? mulmod(b, q, m) : q;
25 | }
26 |
27 | bool es_primo_prob(ll n, int a) {
28 | if (n == a)
29 | return true;
30 | ll s = 0, d = n - 1;
31 | while (d % 2 == 0)
32 | s++, d /= 2;
33 |
34 | ll x = expmod(a, d, n);
35 | if ((x == 1) || (x + 1 == n))
36 | return true;
37 | for (int i = 0; i < s-1; ++i) {
38 | x = mulmod(x, x, n);
39 | if (x == 1)
40 | return false;
41 | if (x + 1 == n)
42 | return true;
43 | }
44 | return false;
45 | }
46 |
47 | bool rabinPrime(ll n) { //devuelve true si n es primo
48 | if (n == 1)
49 | return false;
50 | const int ar[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
51 | for(int j = 0; j < 12; ++j)
52 | if (!es_primo_prob(n, ar[j]))
53 | return false;
54 | return true;
55 | }
56 |
57 | ll rho(ll n) {
58 | if ((n & 1) == 0)
59 | return 2;
60 | ll x = 2, y = 2, d = 1;
61 | ll c = rand() % n + 1;
62 | while (d == 1) {
63 | x = (mulmod(x, x, n) + c) % n;
64 | y = (mulmod(y, y, n) + c) % n;
65 | y = (mulmod(y, y, n) + c) % n;
66 | if (x - y >= 0)
67 | d = gcd(x - y, n);
68 | else
69 | d = gcd(y - x, n);
70 | }
71 | return d == n ? rho(n) : d;
72 | }
73 | void factRho(ll n, map &prim) { // O( (logN)^3 )
74 | if (n == 1)
75 | return;
76 | if (rabinPrime(n)) {
77 | prim[n]++;
78 | return;
79 | }
80 | ll factor = rho(n);
81 | factRho(factor, prim);
82 | factRho(n / factor, prim);
83 | }
84 | }
--------------------------------------------------------------------------------
/Codes/Math/BitVector.cpp:
--------------------------------------------------------------------------------
1 | struct BitVector {
2 | typedef unsigned long long ULong;
3 | vector bits;
4 | vector acu;
5 | struct reference {
6 | BitVector &o; int p, b;
7 | reference(BitVector &o, int p) : o(o), p(p/64), b(p&63) { }
8 | bool operator=(bool v) const {
9 | if (v) o.bits[p] |= 1ULL << b;
10 | else o.bits[p] &= ~(1ULL << b);
11 | return v;
12 | }
13 | };
14 | BitVector(ULong n = 0) : bits(1, n), acu(1, __builtin_popcountll(n)) { recompute(); }
15 | BitVector(string s, char one = '1') {
16 | reverse(s.begin(), s.end());
17 | bits = vector(s.size() / 64 + 1);
18 | for (int i = 0; i < s.size(); ++i)
19 | if (s[i] == one)
20 | bits[i / 64] |= 1ULL << (i & 63);
21 | while (bits.size() > 1 && bits.back() == 0) bits.pop_back();
22 | recompute();
23 | }
24 | BitVector& operator<<=(const int n) {
25 | int osz = bits.size();
26 | int whole = n / 64;
27 | int extra = n % 64;
28 | bits.resize(bits.size() + n / 64 + 1);
29 | for (int i = osz - 1; i >= 0; --i) {
30 | ULong x = bits[i]; bits[i] = 0;
31 | bits[i + whole] |= x << extra;
32 | bits[i + whole + 1] |= x >> (64 - extra);
33 | }
34 | while (bits.size() > 1 && bits.back() == 0) bits.pop_back();
35 | recompute();
36 | }
37 | BitVector operator<<(const int n) {
38 | BitVector o = *this; o <<= n; return o;
39 | }
40 | BitVector& operator>>=(const int n) {
41 | int whole = n / 64;
42 | int extra = n % 64;
43 | for (int i = 0; i < whole; ++i) bits[i] = 0;
44 | for (int i = whole; i < bits.size(); ++i) {
45 | ULong x = bits[i]; bits[i] = 0;
46 | bits[i - whole] |= x >> extra;
47 | bits[i - whole - 1] |= x << (64 - extra);
48 | }
49 | while (bits.size() > 1 && bits.back() == 0) bits.pop_back();
50 | recompute();
51 | }
52 | BitVector operator>>(const int n) {
53 | BitVector o = *this; o >>= n; return o;
54 | }
55 | BitVector operator&(const BitVector o) const {
56 | BitVector r;
57 | r.bits.resize(min(bits.size(), o.bits.size()));
58 | for (int i = 0; i < r.bits.size(); ++i) r.bits[i] = bits[i] & o.bits[i];
59 | return r;
60 | }
61 | reference operator[](int p) { return reference(*this, p); }
62 | bool operator[](int p) const { return (bits[p / 64] >> (p & 63)) & 1; }
63 | void recompute() {
64 | acu.resize(bits.size());
65 | for (int i = 0; i < bits.size(); ++i) {
66 | acu[i] = __builtin_popcountll(bits[i]);
67 | if (i > 0) acu[i] += acu[i-1];
68 | }
69 | }
70 | friend ostream &operator<<(ostream &os, const BitVector &bitVector) {
71 | for (int i = bitVector.bits.size() - 1; i >= 0; --i) {
72 | os << bitset<64>(bitVector.bits[i]);
73 | }
74 | return os;
75 | }
76 | };
77 |
--------------------------------------------------------------------------------
/Codes/Math/Convolution.java:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 | import java.util.ArrayList;
3 | import java.util.Arrays;
4 | import java.util.Collections;
5 | import java.util.StringTokenizer;
6 | import java.io.BufferedReader;;
7 |
8 | public class Main {
9 | static int MOD = 1000000007;
10 |
11 | public static void main(String[] args) {
12 | // TODO Auto-generated method stub
13 | Double a[] = {1.0, 3.0, 4.0, 5.0, 7.0};
14 | Double b[] = {2.0, 4.0, 6.0};
15 |
16 | FFT fft = new FFT();
17 | ArrayList c = fft.Convolution(
18 | (ArrayList) Arrays.asList(a),
19 | (ArrayList) Arrays.asList(b)
20 | );
21 | for(Double d : c){
22 | System.out.println(d);
23 | }
24 |
25 | }
26 | static class Complex {
27 | double x,y;
28 | Complex(double x, double y){
29 | this.x = x;
30 | this.y = y;
31 | }
32 | double real(){
33 | return x;
34 | }
35 | Complex multiply(Complex c){
36 | return new Complex(x*c.x - y*c.y, x*c.y + y*c.x);
37 | }
38 | Complex divide(Complex c){
39 | double m = c.x*c.x - c.y*c.y;
40 | return new Complex(x / m , y / m).multiply(new Complex(c.x,-c.y));
41 | }
42 | Complex add(Complex c){
43 | return new Complex(x+c.x,y+c.y);
44 | }
45 | static Complex exp(Complex c){
46 | return new Complex(c.x*Math.cos(c.y), c.x*Math.sin(c.y));
47 | }
48 | static Complex ONE(){
49 | return new Complex(1,0);
50 | }
51 | static Complex ZERO(){
52 | return new Complex(0,0);
53 | }
54 | }
55 | static class FFT
56 | {
57 | public FFT(){
58 |
59 | }
60 | ArrayList A;
61 | int n, L;
62 |
63 | int ReverseBits(int k) {
64 | int ret = 0;
65 | for (int i = 0; i < L; i++) {
66 | ret = (ret << 1) | (k & 1);
67 | k >>= 1;
68 | }
69 | return ret;
70 | }
71 |
72 | void BitReverseCopy(ArrayList a) {
73 | for (n = 1, L = 0; n < a.size(); n <<= 1, L++)
74 | ;
75 | A.addAll(Collections.nCopies(n-A.size(), new Complex(0,0)));
76 | for (int k = 0; k < n; k++)
77 | A.set(ReverseBits(k), a.get(k));
78 | }
79 |
80 | ArrayList DFT(ArrayList a, boolean inverse) {
81 | BitReverseCopy(a);
82 | for (int s = 1; s <= L; s++) {
83 | int m = 1 << s;
84 | Complex wm = Complex.exp(new Complex(0.0, 2.0 * Math.PI / m));
85 | if (inverse)
86 | wm = Complex.ONE().divide(wm);
87 | for (int k = 0; k < n; k += m) {
88 | Complex w = Complex.ONE();
89 | for (int j = 0; j < m / 2; j++) {
90 | Complex t = w.multiply(A.get(k + j + m / 2));
91 | Complex u = w.multiply(A.get(k + j));
92 | A.set(k + j, u.add(t));
93 | A.set(k + j + m / 2, u.add(t));
94 | w = w.multiply(wm);
95 | }
96 | }
97 | }
98 | if (inverse)
99 | for (int i = 0; i < n; i++)
100 | A.get(i).divide(new Complex(n,0));
101 | return A;
102 | }
103 |
104 | // c[k] = sum_{i=0}^k a[i] b[k-i]
105 | ArrayList Convolution(ArrayList a, ArrayList b) {
106 | int L = 1;
107 | while ((1 << L) < a.size())
108 | L++;
109 | while ((1 << L) < b.size())
110 | L++;
111 | int n = 1 << (L + 1);
112 |
113 | ArrayList aa = new ArrayList();
114 | ArrayList bb = new ArrayList();
115 | for (int i = 0; i < n; i++)
116 | aa.add(i < a.size() ? new Complex(a.get(i), 0) : Complex.ZERO());
117 | for (int i = 0; i < n; i++)
118 | bb.add(i < b.size() ? new Complex(b.get(i), 0) : Complex.ZERO());
119 |
120 | ArrayList AA = DFT(aa, false);
121 | ArrayList BB = DFT(bb, false);
122 | ArrayList CC = new ArrayList();
123 | for (int i = 0; i < AA.size(); i++)
124 | CC.add(AA.get(i).multiply(BB.get(i)));
125 | ArrayList cc = DFT(CC, true);
126 |
127 | ArrayList c = new ArrayList();
128 | for (int i = 0; i < a.size() + b.size() - 1; i++)
129 | c.add(cc.get(i).real());
130 | return c;
131 | }
132 |
133 | }
134 |
135 | }
136 |
--------------------------------------------------------------------------------
/Codes/Math/DiscreteLogarithm-PollardRho.cpp:
--------------------------------------------------------------------------------
1 |
2 | int modPow(int b, int e, int m) {
3 | if (e == 0) return 1;
4 | int sq = modPow(b, e >> 1, m);
5 | sq = 1LL * sq * sq % m;
6 | return (e & 1) ? (sq * 1LL * b % m) : sq;
7 | }
8 | // a*x = b (mod m)
9 | int solveLinearCongruence(int a, int b, int m) {
10 | if (b == 0) return 0;
11 | if (a == 0) return -1;
12 | if (a == 1) return b;
13 | int y = solveLinearCongruence(m % a, (-b % a + a) % a, a);
14 | return y < 0 ? y : (1LL*m*y+b) / a % m;
15 | }
16 | // a^output = b
17 | int discreteLogarithm2(int a, int b, int m) {
18 | int o = m-1;
19 | auto sub = [] (int a, int b, int m) { return ((a - b) % m + m) % m; };
20 | auto gen = [&](Long &x, Long &p, Long &q) {
21 | switch (x % 3) {
22 | case 0: x = x * x % m, p = p * 2 % o, q = q * 2 % o; break;
23 | case 1: x = x * a % m, p = (p == o-1) ? 0 : p+1; break;
24 | case 2: x = x * b % m, q = (q == o-1) ? 0 : q+1; break;
25 | }
26 | };
27 | Long x = 1, p = 0, q = 0;
28 | Long X = x, P = p, Q = q;
29 | for (int i = 1; ; ++i) {
30 | gen(x, p, q);
31 | gen(X, P, Q); gen(X, P, Q); // double step
32 | if (x == X) {
33 | int r = sub(q, Q, o);
34 | int num = sub(P, p, o);
35 | if (r == 0) return -1;
36 | int gc = __gcd(r, o);
37 | int s = solveLinearCongruence(r, num, o);
38 | if (s == -1) return -1;
39 | for (int t = 0; t < gc; ++t) {
40 | int cn = s + o / gc * t;
41 | if (modPow(a, cn, m) == b) {
42 | return cn;
43 | }
44 | }
45 | return -1;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Codes/Math/DiscreteLogarithm.cpp:
--------------------------------------------------------------------------------
1 | Long discreteLogarithm(Long base, Long x, Long mod) {
2 | assert(x > 0);
3 | if (x == 1) return 0;
4 | Long n = (int) sqrt (mod) + 1;
5 | Long an = 1;
6 | for (int i = 0; i value;
9 | for (Long i = 1, cur = an; i<= n; ++i) {
10 | if (value.count(cur) == 0)
11 | value[ cur ] = i;
12 | cur = (cur * an) % mod;
13 | }
14 | for (Long i = 0, cur = x; i<= n; ++i) {
15 | if (value.count(cur)) {
16 | Long ans = value[cur] * n - i;
17 | if (ans < mod)
18 | return ans;
19 | }
20 | cur = (cur * base) % mod;
21 | }
22 | return -1;
23 | }
24 |
--------------------------------------------------------------------------------
/Codes/Math/EducationalFFT.cpp:
--------------------------------------------------------------------------------
1 | namespace EducationalFFT {
2 | /*
3 | X0,...,N−1 ← ditfft2(x, N, s): DFT of (x0, xs, x2s, ..., x(N-1)s):
4 | if N = 1 then
5 | X0 ← x0 trivial size-1 DFT base case
6 | else
7 | X0,...,N/2−1 ← ditfft2(x, N/2, 2s) DFT of (x0, x2s, x4s, ...)
8 | XN/2,...,N−1 ← ditfft2(x+s, N/2, 2s) DFT of (xs, xs+2s, xs+4s, ...)
9 | for k = 0 to N/2−1 combine DFTs of two halves into full DFT:
10 | t ← Xk
11 | Xk ← t + exp(−2πi s k/N) Xk+N/2
12 | Xk+N/2 ← t − exp(−2πi s k/N) Xk+N/2
13 | endfor
14 | endif
15 | */
16 | typedef complex Complex;
17 | long double PI = acos(-1.0L);
18 | struct ExpBucket {
19 | vector E, I;
20 | int N;
21 | ExpBucket(int N):E(N), I(N),N(N){
22 | for(int i = 0; i < N; ++i){
23 | E[i] = exp(Complex(0, -2.0L*PI*i/N));
24 | I[i] = exp(Complex(0, 2.0L*PI*i/N));
25 | }
26 | }
27 | Complex get(int i, int n, int inv){
28 | i *= N / n;
29 | return inv == 1 ? E[i] : I[i];
30 | }
31 | };
32 | vector dft(ExpBucket &E, const vector &x, int n, int inv = 1, int st = 0, int s = 1) {
33 | if(n == 1){
34 | return vector(1, x[st]);
35 | }
36 | vector X0 = dft(E, x, n/2, inv, st, 2*s);
37 | vector X1 = dft(E, x, n/2, inv, st + s, 2*s);
38 | vector X;
39 | X.insert(X.end(), X0.begin(), X0.end());
40 | X.insert(X.end(), X1.begin(), X1.end());
41 | for(int k = 0; k <= n/2-1; ++k){
42 | Complex a = X[k];
43 | Complex b = X[k + n/2];
44 | /* sin(2*pi*s*i/n) */
45 | long double ang = -2*PI*k/n*inv;
46 | Complex eb = exp(Complex(0, ang)) * b;
47 | X[k] = a + eb ;
48 | X[k+n/2] = a - eb;
49 | }
50 | return X;
51 | }
52 | vector convolution(vector A, vector B){
53 | int n = max(A.size(), B.size());
54 | reverse(B.begin(),B.end());
55 | while( n != (n & -n))n++;
56 | n <<= 1;
57 | A.resize(n);
58 | B.resize(n);
59 | ExpBucket E(n);
60 | A = dft(E, A, A.size(), 1);
61 | B = dft(E, B, B.size(), 1);
62 | for (int i = 0; i < A.size(); ++i) {
63 | A[i] = A[i] * B[i];
64 | }
65 | vector C = dft(E, A, A.size(), -1);
66 | for (Complex &v : C) {
67 | if(abs(v.real()) < 1e-9)v.real(0);
68 | if(abs(v.imag()) < 1e-9)v.imag(0);
69 | v.real(v.real() / A.size());
70 | v.imag(v.imag() / A.size());
71 | assert(abs(v.imag()) < 0.2);
72 | assert(abs(v.real() - round(v.real())) < 0.2);
73 | }
74 | return C;
75 | }
76 | vector convolution2(vector A, vector B){
77 | int n = max(A.size(), B.size());
78 | reverse(B.begin(),B.end());
79 | while( n != (n & -n))n++;
80 | n <<= 1;
81 | A.resize(n);
82 | B.resize(n);
83 | ExpBucket E(n);
84 | vector T(n);
85 | for (int i = 0; i < n; ++i) {
86 | T[i] = Complex(A[i].real(), B[i].real());
87 | }
88 | T = dft(E, T, T.size(), 1);
89 | vector T2(n);
90 | for (int i = 0; i < n; ++i) {
91 | Complex X = (T[i] + conj(T[(n - i) % n])) / Complex(2, 0);
92 | Complex Y = (T[i] - conj(T[(n - i) % n])) / Complex(0, 2);
93 | T2[i] = X*Y;
94 | }
95 | vector C = dft(E, T2, T2.size(), -1);
96 | for (Complex &v : C) {
97 | if(abs(v.real()) < 1e-9)v.real(0);
98 | if(abs(v.imag()) < 1e-9)v.imag(0);
99 | v.real(v.real() / A.size());
100 | v.imag(v.imag() / A.size());
101 | assert(abs(v.imag()) < 0.2);
102 | assert(abs(v.real() - round(v.real())) < 0.2);
103 | }
104 | return C;
105 | }
106 | }
--------------------------------------------------------------------------------
/Codes/Math/Equations/BitGauss.cpp:
--------------------------------------------------------------------------------
1 | template
2 | vector bitGauss(VVI m){ // last column is arbitratry integer
3 | int R = m.size(), C = m[0].size();
4 | vector> B(R);
5 | for (int i = 0; i < R; ++i) {
6 | for (int j = 0; j < C; ++j) {
7 | B[i][j] = m[i][j];
8 | }
9 | }
10 | int pivot = 0;
11 | for (int r = 0; r < R && pivot+1 < C; ) {
12 | bool f = 0;
13 | for (int i = r; i < B.size(); ++i) {
14 | if(B[i][pivot]){
15 | f = 1;
16 | swap(B[i], B[r]);
17 | break;
18 | }
19 | }
20 | if(f){
21 | for (int i = r+1; i < B.size(); ++i) {
22 | if(B[i][pivot]){
23 | B[i] ^= B[r];
24 | }
25 | }
26 | r++;
27 | }
28 | pivot++;
29 | }
30 | for (int i = R-1; i >= 0; --i) {
31 | for (int j = 0; j < C; ++j) {
32 | if(B[i][j]){
33 | for (int k = i-1; k >= 0; --k) {
34 | if(B[k][j]){
35 | B[k] ^= B[i];
36 | }
37 | }
38 | break;
39 | }
40 | }
41 | }
42 | for (int i = 0; i < R; ++i) {
43 | for (int j = 0; j < C; ++j) {
44 | m[i][j] = B[i][j];
45 | }
46 | }
47 | return m;
48 | }
--------------------------------------------------------------------------------
/Codes/Math/Equations/GaussDouble.cpp:
--------------------------------------------------------------------------------
1 | vector> gauss(vector> m){
2 | int pivot = 0;
3 | for (int r = 0; r < m.size() && pivot+1 < m[0].size(); ) {
4 | int f = 0;
5 | for (int i = r; i < m.size(); ++i) {
6 | if(abs(m[i][pivot]) > 1e-5){
7 | f = 1;
8 | swap(m[i], m[r]);
9 | break;
10 | }
11 | }
12 | if(f){
13 | for (int j = m[0].size()-1; j >= pivot ; --j) {
14 | m[r][j] /= m[r][pivot];
15 | }
16 | for (int i = r+1; i < m.size(); ++i) {
17 | if(m[i][pivot]){
18 | for (int j = m[0].size()-1; j >= pivot; --j) {
19 | OPS++;
20 | m[i][j] -= m[i][pivot] * m[r][j];
21 | }
22 | }
23 | }
24 | r++;
25 | }
26 | pivot++;
27 | }
28 | for (int i = m.size()-1; i >= 0; --i) {
29 | for (int j = 0; j+1 < m[0].size(); ++j) {
30 | if(m[i][j]){
31 | for (int k = i-1; k >= 0; --k) {
32 | if(m[k][j]){
33 | for (int l = m[0].size()-1; l >= j; --l) {
34 | OPS++;
35 | m[k][l] -= m[k][j] * m[i][l];
36 | }
37 | }
38 | }
39 | break;
40 | }
41 | }
42 | }
43 | return m;
44 | }
--------------------------------------------------------------------------------
/Codes/Math/Equations/VectorSpace.cpp:
--------------------------------------------------------------------------------
1 | #define DIM 10
2 | typedef bitset vec;
3 | struct VectorSpace {
4 | int cnt, cols;
5 | vector< vec > R; // rules to apply to that row
6 | vector< vec > V;
7 | VectorSpace(): cnt(0), cols(0), R(DIM), V(DIM) {
8 | for (int i = 0; i < DIM; ++i)
9 | R[i][i] = 1;
10 | }
11 | void add(vec nv) { // DIM^2 / 64
12 | cnt++;
13 | if (cols == DIM) return; // space complete
14 | if (nv.none()) return;
15 | vec nc = applyRules(nv);
16 | int firstOne = findFirstOne(nc, cols);
17 | if (firstOne == -1) return;
18 | nc[firstOne] = 0; nc[cols] = 1; // swap
19 | swap(R[firstOne], R[cols]);
20 | for (int i = cols+1; i < DIM; ++i) {
21 | if (nc[i]) {
22 | nc[i] = 0;
23 | R[i] = R[i] ^ R[cols];
24 | }
25 | }
26 | for (int i = 0; i < DIM; ++i) {
27 | V[i][cols] = nc[i];
28 | }
29 | cols++;
30 | }
31 | vec applyRules(const vec &nv) { // DIM^2 / 64
32 | vec ret;
33 | for (int i = 0; i < DIM; ++i) { // apply rules for all rows
34 | ret[i] = (nv & R[i]).count() & 1;
35 | }
36 | return ret;
37 | }
38 | static int findFirstOne(const vec &nv, int start = 0) { // DIM
39 | for (int i = start; i < DIM; ++i) {
40 | if (nv[i]) return i;
41 | }
42 | return -1;
43 | }
44 | bool possible(const vec &nv) {
45 | vec nc = applyRules(nv);
46 | return findFirstOne(nc, cols) == -1;
47 |
48 | }
49 | int ways(const vec &nv) {
50 | vec nc = applyRules(nv);
51 | if (findFirstOne(nc, cols) != -1) return 0;
52 | return pow(2.0, cnt - cols); // use modPow if needed
53 | }
54 | };
55 |
--------------------------------------------------------------------------------
/Codes/Math/Factors.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 | struct Factors
5 | {
6 | static vector factorize(int N)
7 | {
8 | vector ANS; ANS.reserve(200);
9 | while(N % 2 == 0) ANS.push_back(2), N /= 2;
10 | for(int i = 3; i*i <= N && N > 1; i += 2)
11 | {
12 | while(N % i == 0)
13 | {
14 | ANS.push_back(i);
15 | N /= i;
16 | }
17 | }
18 | if(N > 1)ANS.push_back(N);
19 | return ANS;
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/Codes/Math/FastestFFT.cpp:
--------------------------------------------------------------------------------
1 | typedef long long Long;
2 | typedef long double Double;
3 | typedef long long Long;
4 | typedef vector VI;
5 | struct point {
6 | Double x, y;
7 | point(Double x = 0, Double y = 0) : x(x), y(y) { }
8 | point conjugate() const { return point(x, -y); }
9 | };
10 | point operator+(const point &a, const point &b) { return {a.x + b.x, a.y + b.y}; }
11 | point operator-(const point &a, const point &b) { return {a.x - b.x, a.y - b.y}; }
12 | point operator*(const point &a, const point &b) { return {a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x}; }
13 | point operator/(const point &a, Double d) { return {a.x / d, a.y / d}; }
14 | void fft(vector &a, int sign = +1) {
15 | int n = a.size();
16 | for (int i = 1, j = 0; i < n - 1; ++i) {
17 | for (int k = n >> 1; (j ^= k) < k; k >>= 1);
18 | if (i < j) swap(a[i], a[j]);
19 | }
20 | Double theta = 2 * atan2(0, -1) * sign;
21 | for (int m, mh = 1; (m = mh << 1) <= n; mh = m) {
22 | point wm(cos(theta / m), sin(theta / m)), w(1, 0);
23 | for (int i = 0; i < n; i += m, w = point(1, 0))
24 | for (int j = i, k = j + mh; j < i + mh; ++j, ++k, w = w * wm) {
25 | point x = a[j], y = a[k] * w;
26 | a[j] = x + y;
27 | a[k] = x - y;
28 | }
29 | }
30 | if (sign == -1) for (point &p : a) p = p / n;
31 | }
32 | VI convolution(const VI &a, const VI &b, int isStraight = true) {
33 | vector ca(a.size()), cb(b.size());
34 | for (int i = 0; i < ca.size(); ++i) ca[i] = a[i];
35 | for (int i = 0; i < cb.size(); ++i) cb[i] = b[i];
36 | int L = 1;
37 | if (isStraight) reverse(cb.begin(), cb.end());
38 | while (L < a.size() + b.size() - 1) L *= 2;
39 | ca.resize(L); cb.resize(L);
40 | vector c(L);
41 | fft(ca, 1); fft(cb, 1);
42 | for (int i = 0; i < L; ++i) c[i] = ca[i] * cb[i];
43 | fft(c, -1);
44 | c.resize(a.size() + b.size() - 1);
45 | vector cc(c.size());
46 | for (int i = 0; i < c.size(); ++i)
47 | cc[i] = round(c[i].x); // dont truncate use round
48 | return cc;
49 | }
50 | // add code below for BigConvolution
51 | point operator/(const point &a, const point &b) {
52 | Double m = b.x * b.x + b.y * b.y;
53 | return point(a.x / m, a.y / m) * point(b.x, -b.y);
54 | }
55 | Long mround(Double A) {
56 | Long F = A;
57 | if (A < 0) F = (Long) (A - 0.5);
58 | if (A > 0) F = (Long) (A + 0.5);
59 | return F;
60 | }
61 | VI BigConvolution(const VI &a, const VI &b, Long MOD) {
62 | int ssss = a.size() + b.size() - 1;
63 | if (ssss <= 1024) { // remove this code if ans never less than 1024
64 | vector bf(ssss);
65 | for (int i = 0; i < a.size(); ++i) {
66 | for (int j = 0; j < b.size(); ++j) {
67 | bf[i + j] = (bf[i + j] + 1LL * a[i] * b[j]) % MOD;
68 | }
69 | }
70 | return bf;
71 | }
72 | int L = 1;
73 | while ((1 << L) < a.size()) L++;
74 | while ((1 << L) < b.size()) L++;
75 | int n = 1 << (L + 1);
76 | Long SH = 16;
77 | Long M = (1 << SH) - 1, S = 1 << SH;
78 | Long S1 = S;
79 | Long S2 = S * S % MOD;
80 | vector xy1(n), xy0(n);
81 | for (int i = 0; i < a.size(); ++i) {
82 | xy1[i].x = a[i] >> SH;
83 | xy0[i].x = a[i] & M;
84 | }
85 | for (int i = 0; i < b.size(); ++i) {
86 | xy1[i].y = b[i] >> SH;
87 | xy0[i].y = b[i] & M;
88 | }
89 | fft(xy1, 1); fft(xy0, 1);
90 | vector