Skip to content
Snippets Groups Projects
Commit 3851fd98 authored by Bruno Freitas Tissei's avatar Bruno Freitas Tissei
Browse files

Add Karatsuba

parent ff512a6b
No related branches found
No related tags found
No related merge requests found
/// Kruskal /// Kruskal
/// ///
///
///
/// Time: O(E log V) /// Time: O(E log V)
/// Space: O(E) /// Space: O(E)
/// ///
...@@ -17,11 +15,7 @@ struct Kruskal { ...@@ -17,11 +15,7 @@ struct Kruskal {
Kruskal(int N) : N(N), ds(N) {} 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) { int run(vector<iii> &mst) {
// Sort by weight of the edges
sort(all(edges), [&](const iii &a, const iii &b) { sort(all(edges), [&](const iii &a, const iii &b) {
// ('>' for maximum spanning tree) // ('>' for maximum spanning tree)
return a.se < b.se; return a.se < b.se;
...@@ -32,8 +26,6 @@ struct Kruskal { ...@@ -32,8 +26,6 @@ struct Kruskal {
int pu = ds.find_set(edges[i].fi.fi); int pu = ds.find_set(edges[i].fi.fi);
int pv = ds.find_set(edges[i].fi.se); 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) { if (pu != pv) {
mst.pb(edges[i]); mst.pb(edges[i]);
size += edges[i].se; size += edges[i].se;
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
/// ///
/// Status: Tested (KRAKOVIA) /// Status: Tested (KRAKOVIA)
/// Caution: Just use python. /// Caution: Just use python.
/// Include:
/// - math/karatsuba
const int base = 1000000000; const int base = 1000000000;
const int base_d = 9; const int base_d = 9;
...@@ -31,7 +33,6 @@ struct BigInt { ...@@ -31,7 +33,6 @@ struct BigInt {
BigInt operator+(const BigInt &x) const { BigInt operator+(const BigInt &x) const {
if (sign != x.sign) return *this - (-x); if (sign != x.sign) return *this - (-x);
int carry = 0; int carry = 0;
BigInt res = x; BigInt res = x;
...@@ -85,8 +86,8 @@ struct BigInt { ...@@ -85,8 +86,8 @@ struct BigInt {
return res; return res;
} }
friend pair<BigInt, BigInt> divmod(const BigInt &a1, friend pair<BigInt, BigInt> divmod(const BigInt &a1,
const BigInt &b1) const BigInt &b1)
{ {
int norm = base / (b1.back() + 1); int norm = base / (b1.back() + 1);
BigInt a = a1.abs() * norm; BigInt a = a1.abs() * norm;
...@@ -150,23 +151,15 @@ struct BigInt { ...@@ -150,23 +151,15 @@ struct BigInt {
return m * sign; return m * sign;
} }
void operator+=(const BigInt &x) { void operator+=(const BigInt &x) { *this = *this + 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) { void operator/=(const BigInt &x) { *this = *this / 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 { bool operator<(const BigInt &x) const {
if (sign != x.sign) if (sign != x.sign)
return sign < x.sign; return sign < x.sign;
if (size() != x.size()) if (size() != x.size())
return size() * sign < x.size() * x.sign; return size() * sign < x.size() * x.sign;
...@@ -224,17 +217,17 @@ struct BigInt { ...@@ -224,17 +217,17 @@ struct BigInt {
friend BigInt gcd(const BigInt &a, const BigInt &b) { friend BigInt gcd(const BigInt &a, const BigInt &b) {
return b.is_zero() ? a : gcd(b, a % b); return b.is_zero() ? a : gcd(b, a % b);
} }
friend BigInt lcm(const BigInt &a, const BigInt &b) { friend BigInt lcm(const BigInt &a, const BigInt &b) {
return a / gcd(a, b) * b; return a / gcd(a, b) * b;
} }
// Transforms string into BigInt.
void read(const string &s) { void read(const string &s) {
sign = 1; sign = 1;
num.clear(); num.clear();
int pos = 0; int pos = 0;
while (pos < s.size() && while (pos < s.size() &&
(s[pos] == '-' || s[pos] == '+')) { (s[pos] == '-' || s[pos] == '+')) {
if (s[pos] == '-') if (s[pos] == '-')
sign = -sign; sign = -sign;
...@@ -268,9 +261,9 @@ struct BigInt { ...@@ -268,9 +261,9 @@ struct BigInt {
return stream; return stream;
} }
static vector<int> convert_base(const vector<int> &a, static vector<int> convert_base(
int oldd, int newd) const vector<int> &a,
{ int oldd, int newd) {
vector<ll> p(max(oldd, newd) + 1); vector<ll> p(max(oldd, newd) + 1);
p[0] = 1; p[0] = 1;
for (int i = 1; i < p.size(); i++) for (int i = 1; i < p.size(); i++)
...@@ -297,44 +290,6 @@ struct BigInt { ...@@ -297,44 +290,6 @@ struct BigInt {
return res; 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 { BigInt operator*(const BigInt &x) const {
vector<int> a6 = convert_base(this->num, base_d, 6); vector<int> a6 = convert_base(this->num, base_d, 6);
vector<int> b6 = convert_base(x.num, base_d, 6); vector<int> b6 = convert_base(x.num, base_d, 6);
...@@ -344,10 +299,11 @@ struct BigInt { ...@@ -344,10 +299,11 @@ struct BigInt {
while (a.size() < b.size()) a.pb(0); while (a.size() < b.size()) a.pb(0);
while (b.size() < a.size()) b.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); a.pb(0), b.pb(0);
vector<ll> c = karatsuba(a, b); Karatsuba karatsuba;
vector<ll> c = karatsuba.run(a, b);
BigInt res; BigInt res;
int carry = 0; int carry = 0;
......
/// 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;
}
};
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment