diff --git a/algorithms/graph/kruskal.cpp b/algorithms/graph/kruskal.cpp index 15218e7feb68f422a665e0b2ac852c77f050d4eb..2f86011a94ce12f60d1404de51dafb67426db106 100644 --- a/algorithms/graph/kruskal.cpp +++ b/algorithms/graph/kruskal.cpp @@ -1,7 +1,5 @@ /// Kruskal /// -/// -/// /// Time: O(E log V) /// Space: O(E) /// @@ -17,11 +15,7 @@ struct Kruskal { Kruskal(int N) : N(N), ds(N) {} - // Returns value of MST and fills mst vector with - // the edges from the MST. int run(vector<iii> &mst) { - - // Sort by weight of the edges sort(all(edges), [&](const iii &a, const iii &b) { // ('>' for maximum spanning tree) return a.se < b.se; @@ -32,8 +26,6 @@ struct Kruskal { int pu = ds.find_set(edges[i].fi.fi); int pv = ds.find_set(edges[i].fi.se); - // If the sets are different, then the edge i does - // not close a cycle if (pu != pv) { mst.pb(edges[i]); size += edges[i].se; diff --git a/algorithms/math/big_integer.cpp b/algorithms/math/big_integer.cpp index f88c09f0d43e6a46947257b07523f79d4f69de14..bc69d5eaec850bdecec2cb4022ae0b3dd1603cf9 100644 --- a/algorithms/math/big_integer.cpp +++ b/algorithms/math/big_integer.cpp @@ -4,6 +4,8 @@ /// /// Status: Tested (KRAKOVIA) /// Caution: Just use python. +/// Include: +/// - math/karatsuba const int base = 1000000000; const int base_d = 9; @@ -31,7 +33,6 @@ struct BigInt { BigInt operator+(const BigInt &x) const { if (sign != x.sign) return *this - (-x); - int carry = 0; BigInt res = x; @@ -85,8 +86,8 @@ struct BigInt { return res; } - friend pair<BigInt, BigInt> divmod(const BigInt &a1, - const BigInt &b1) + friend pair<BigInt, BigInt> divmod(const BigInt &a1, + const BigInt &b1) { int norm = base / (b1.back() + 1); BigInt a = a1.abs() * norm; @@ -150,23 +151,15 @@ struct BigInt { return m * sign; } - void operator+=(const BigInt &x) { - *this = *this + x; - } - void operator-=(const BigInt &x) { - *this = *this - x; - } - void operator*=(const BigInt &x) { - *this = *this * x; - } - void operator/=(const BigInt &x) { - *this = *this / x; - } + void operator+=(const BigInt &x) { *this = *this + x; } + void operator-=(const BigInt &x) { *this = *this - x; } + void operator*=(const BigInt &x) { *this = *this * x; } + void operator/=(const BigInt &x) { *this = *this / x; } bool operator<(const BigInt &x) const { if (sign != x.sign) return sign < x.sign; - + if (size() != x.size()) return size() * sign < x.size() * x.sign; @@ -224,17 +217,17 @@ struct BigInt { friend BigInt gcd(const BigInt &a, const BigInt &b) { return b.is_zero() ? a : gcd(b, a % b); } + friend BigInt lcm(const BigInt &a, const BigInt &b) { return a / gcd(a, b) * b; } - // Transforms string into BigInt. void read(const string &s) { sign = 1; num.clear(); int pos = 0; - while (pos < s.size() && + while (pos < s.size() && (s[pos] == '-' || s[pos] == '+')) { if (s[pos] == '-') sign = -sign; @@ -268,9 +261,9 @@ struct BigInt { return stream; } - static vector<int> convert_base(const vector<int> &a, - int oldd, int newd) - { + static vector<int> convert_base( + const vector<int> &a, + int oldd, int newd) { vector<ll> p(max(oldd, newd) + 1); p[0] = 1; for (int i = 1; i < p.size(); i++) @@ -297,44 +290,6 @@ struct BigInt { return res; } - static vector<ll> karatsuba(const vector<ll> &a, - const vector<ll> &b) - { - int n = a.size(); - vector<ll> res(n + n); - - if (n <= 32) { - for (int i = 0; i < n; i++) - for (int j = 0; j < n; j++) - res[i + j] += a[i] * b[j]; - return res; - } - - int k = n >> 1; - vector<ll> a1(a.begin(), a.begin() + k); - vector<ll> a2(a.begin() + k, a.end()); - vector<ll> b1(b.begin(), b.begin() + k); - vector<ll> b2(b.begin() + k, b.end()); - - vector<ll> a1b1 = karatsuba(a1, b1); - vector<ll> a2b2 = karatsuba(a2, b2); - - for (int i = 0; i < k; i++) - a2[i] += a1[i]; - for (int i = 0; i < k; i++) - b2[i] += b1[i]; - - vector<ll> r = karatsuba(a2, b2); - for (int i = 0; i < a1b1.size(); i++) r[i] -= a1b1[i]; - for (int i = 0; i < a2b2.size(); i++) r[i] -= a2b2[i]; - - for (int i = 0; i < r.size(); i++) res[i + k] += r[i]; - for (int i = 0; i < a1b1.size(); i++) res[i] += a1b1[i]; - for (int i = 0; i < a2b2.size(); i++) res[i + n] += a2b2[i]; - - return res; - } - BigInt operator*(const BigInt &x) const { vector<int> a6 = convert_base(this->num, base_d, 6); vector<int> b6 = convert_base(x.num, base_d, 6); @@ -344,10 +299,11 @@ struct BigInt { while (a.size() < b.size()) a.pb(0); while (b.size() < a.size()) b.pb(0); - while (a.size() & (a.size() - 1)) + while (a.size() & (a.size() - 1)) a.pb(0), b.pb(0); - vector<ll> c = karatsuba(a, b); + Karatsuba karatsuba; + vector<ll> c = karatsuba.run(a, b); BigInt res; int carry = 0; diff --git a/algorithms/math/karatsuba.cpp b/algorithms/math/karatsuba.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3c5d10fe9f5ef85d0f794e6ae6d837a991e4801 --- /dev/null +++ b/algorithms/math/karatsuba.cpp @@ -0,0 +1,48 @@ +/// Karatsuba +/// +/// Time: O(n^{log(3)}) +/// Space: O(n) + +struct Karatsuba { + vector<ll> run(const vector<ll> &a, const vector<ll> &b) { + int n = a.size(); + vector<ll> res(n + n); + + if (n <= 32) { + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + res[i + j] += a[i] * b[j]; + + return res; + } + + int k = n >> 1; + vector<ll> a1(a.begin(), a.begin() + k); + vector<ll> a2(a.begin() + k, a.end()); + vector<ll> b1(b.begin(), b.begin() + k); + vector<ll> b2(b.begin() + k, b.end()); + + vector<ll> a1b1 = run(a1, b1); + vector<ll> a2b2 = run(a2, b2); + + for (int i = 0; i < k; i++) + a2[i] += a1[i]; + for (int i = 0; i < k; i++) + b2[i] += b1[i]; + + vector<ll> r = run(a2, b2); + for (int i = 0; i < a1b1.size(); i++) + r[i] -= a1b1[i]; + for (int i = 0; i < a2b2.size(); i++) + r[i] -= a2b2[i]; + + for (int i = 0; i < r.size(); i++) + res[i + k] += r[i]; + for (int i = 0; i < a1b1.size(); i++) + res[i] += a1b1[i]; + for (int i = 0; i < a2b2.size(); i++) + res[i + n] += a2b2[i]; + + return res; + } +}; diff --git a/caderno.pdf b/caderno.pdf index 3ae532569df79b62bfa711e4c399d821fab6ba0d..f9ce52fea430d4dc1a24f210c59ff867c4b99e5e 100644 Binary files a/caderno.pdf and b/caderno.pdf differ