diff --git a/algorithms/math/binary_exponentiation.cpp b/algorithms/math/binary_exponentiation.cpp index e20f965ab12606745050948856cfb9d82c697a75..799941622dd72372afb300c7d8ecbc8f0a8656fd 100644 --- a/algorithms/math/binary_exponentiation.cpp +++ b/algorithms/math/binary_exponentiation.cpp @@ -3,15 +3,14 @@ /// Time: O(log n) /// Space: O(1) -struct BinExp { - ll run(ll x, ll n) { - ll ans = 1; - while (n) { - if (n & 1) - ans = ans * x; - n >>= 1; - x = x * x; - } - return ans; +template <typename T> +T bin_exp(T x, ll n) { + T ans = 1; + while (n) { + if (n & 1) + ans = ans * x; + n >>= 1; + x = x * x; } -}; + return ans; +} diff --git a/algorithms/math/euler_totient.cpp b/algorithms/math/euler_totient.cpp index 1fbe385abe08d1012cc99388e73e2b41ba5116be..83cf51db771176dea253c75eb1e2334035bac1a9 100644 --- a/algorithms/math/euler_totient.cpp +++ b/algorithms/math/euler_totient.cpp @@ -3,19 +3,17 @@ /// Time: O(sqrt{n}) /// Space: O(1) -struct EulerTotient { - int run(int n) { - int result = n; +int phi(int n) { + int result = n; - for (int i = 2; i*i <= n; i++) - if (n % i == 0) { - while (n % i == 0) n /= i; - result -= result / i; - } + for (int i = 2; i*i <= n; i++) + if (n % i == 0) { + while (n % i == 0) n /= i; + result -= result / i; + } - if (n > 1) - result -= (result / n); + if (n > 1) + result -= (result / n); - return result; - } -}; + return result; +} diff --git a/algorithms/math/extended_euclidean.cpp b/algorithms/math/extended_euclidean.cpp index f1422ebfd759696186396859d6bbf6f699c1e34c..9697789e9116688d063582983f1f66dff8871b0a 100644 --- a/algorithms/math/extended_euclidean.cpp +++ b/algorithms/math/extended_euclidean.cpp @@ -3,19 +3,17 @@ /// Time: O(log min(a,b)) /// Space: O(1) -struct ExtendedEuclidean { - int run(int a, int b, int &x, int &y) { - if (a == 0) { - x = 0, y = 1; - return b; - } +int ext_gcd(int a, int b, int &x, int &y) { + if (a == 0) { + x = 0, y = 1; + return b; + } - int x1, y1; - int g = run(b % a, a, x1, y1); + int x1, y1; + int g = ext_gct(b % a, a, x1, y1); - x = y1 - (b / a) * x1; - y = x1; + x = y1 - (b / a) * x1; + y = x1; - return g; - } -}; + return g; +} diff --git a/algorithms/math/karatsuba.cpp b/algorithms/math/karatsuba.cpp index a3c5d10fe9f5ef85d0f794e6ae6d837a991e4801..22f248f54077b8b3523399be23030207000e695b 100644 --- a/algorithms/math/karatsuba.cpp +++ b/algorithms/math/karatsuba.cpp @@ -3,46 +3,46 @@ /// 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]; +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; +} diff --git a/algorithms/math/legendre.cpp b/algorithms/math/legendre.cpp index 6d1fb75b01820e2df52ad5dd023e126bd5e972f9..d470908d161049f9266b42a289f753c97b7961b4 100644 --- a/algorithms/math/legendre.cpp +++ b/algorithms/math/legendre.cpp @@ -3,15 +3,13 @@ /// Time: O(log_p n) /// Space: O(1) -struct Legendre { - int run(int n, int p) { - int x = 0; +int legendre(int n, int p) { + int x = 0; - while (n) { - n /= p; - x += n; - } - - return x; + while (n) { + n /= p; + x += n; } -}; + + return x; +} diff --git a/algorithms/math/linear_diophantine_equation.cpp b/algorithms/math/linear_diophantine_equation.cpp index 7cdee518550071df799aa9751b45c6eca87d541f..c4a83747e8a13db763ecd62ad153edfdc758f4a2 100644 --- a/algorithms/math/linear_diophantine_equation.cpp +++ b/algorithms/math/linear_diophantine_equation.cpp @@ -24,10 +24,8 @@ struct Diophantine { { init(); } void init() { - ExtendedEuclidean ext_gcd; - int w0, z0; - d = ext_gcd.run(a, b, w0, z0); + d = ext_gcd(a, b, w0, z0); if (c % d == 0) { x0 = w0 * (c / d); y0 = z0 * (c / d); diff --git a/algorithms/math/modular_multiplicative_inverse.cpp b/algorithms/math/modular_multiplicative_inverse.cpp index 97a7dcc9331c32eecc608a57b8454f89793820de..6b08aaef9e8e2133fb9993de32a5441d6137d3ab 100644 --- a/algorithms/math/modular_multiplicative_inverse.cpp +++ b/algorithms/math/modular_multiplicative_inverse.cpp @@ -3,20 +3,15 @@ /// Time: O(log m) /// Space: O(1) -struct ModMultInv { +// Fermat's Little Theorem: Used when m is prime +int fermat(int a, int m) { + return bin_exp(a, m - 2); +} - // Fermat's Little Theorem: Used when m is prime - int fermat(int a, int m) { - BinaryExponentiation bin_exp; - return bin_exp.run(a, m - 2); - } - - // Extended Euclidean Algorithm: Used when m - // and a are coprime - int extended_euclidean(int a, int m) { - ExtendedEuclidean ext_gcd; - int x, y; - int g = ext_gcd.run(a, m, x, y); - return (x % m + m) % m; - } -}; +// Extended Euclidean Algorithm: Used when m +// and a are coprime +int extended_euclidean(int a, int m) { + int x, y; + int g = ext_gcd(a, m, x, y); + return (x % m + m) % m; +} diff --git a/algorithms/math/sieve_of_eratosthenes.cpp b/algorithms/math/sieve_of_eratosthenes.cpp index 853de78926b7c9ea83fa4511a4ebefc6ac4575d1..07e3c668286d4f9c0e4a4ec3bb87a34f1fa78914 100644 --- a/algorithms/math/sieve_of_eratosthenes.cpp +++ b/algorithms/math/sieve_of_eratosthenes.cpp @@ -3,31 +3,18 @@ /// Time: O(n * log log n) /// Space: O(n) -struct Sieve { - int N; - vector<int> is_prime; +vector<int> sieve(int n) { + vector<int> primes; + vector<int> is_prime(n + 1, 1); - Sieve(int N) : - N(N), is_prime(N+1) - { init(); } + for (int p = 2; p*p <= n; ++p) + if (is_prime[p]) + for (int i = p*p; i <= n; i += p) + is_prime[i] = false; - void init() { - fill(all(is_prime), 1); - } + for (int p = 2; p <= n; ++p) + if (is_prime[p]) + primes.pb(p); - vector<int> run() { - vector<int> primes; - init(); - - for (int p = 2; p*p <= N; ++p) - if (is_prime[p]) - for (int i = p*p; i <= N; i += p) - is_prime[i] = false; - - for (int p = 2; p <= N; ++p) - if (is_prime[p]) - primes.pb(p); - - return primes; - } -}; + return primes; +} diff --git a/algorithms/paradigm/edit_distance.cpp b/algorithms/paradigm/edit_distance.cpp index 1704de2736ad22ef8211292e0e1d0ccfed3169f6..e3517d74d4d635623ce37acff41fff34955b0e77 100644 --- a/algorithms/paradigm/edit_distance.cpp +++ b/algorithms/paradigm/edit_distance.cpp @@ -5,21 +5,19 @@ int dp[MAX][MAX]; -struct EditDistance { - int run(string a, string b) { - for (int i = 0; i <= a.size(); ++i) - for (int j = 0; j <= b.size(); ++j) - if (i == 0) - dp[i][j] = j; - else if (j == 0) - dp[i][j] = i; - else if (a[i-1] == b[j-1]) - dp[i][j] = d[i-1][j-1]; - else - dp[i][j] = 1 + min({dp[i][j-1], - dp[i-1][j], - dp[i-1][j-1]}); +int edit_distance(string a, string b) { + for (int i = 0; i <= a.size(); ++i) + for (int j = 0; j <= b.size(); ++j) + if (i == 0) + dp[i][j] = j; + else if (j == 0) + dp[i][j] = i; + else if (a[i-1] == b[j-1]) + dp[i][j] = d[i-1][j-1]; + else + dp[i][j] = 1 + min({dp[i][j-1], + dp[i-1][j], + dp[i-1][j-1]}); - return dp[a.size()][b.size()]; - } -}; + return dp[a.size()][b.size()]; +} diff --git a/algorithms/paradigm/kadane.cpp b/algorithms/paradigm/kadane.cpp index c1458d0de600b6066f4836899a258602edd306a6..ab38c65a6ec34dec34f056eebc643eb1f2325dab 100644 --- a/algorithms/paradigm/kadane.cpp +++ b/algorithms/paradigm/kadane.cpp @@ -3,25 +3,23 @@ /// Time: O(n + m) /// Space: O(n + m) -struct Kadane { - int run(const vector<int> &v, int &start, int &end) { - start = end = 0; - int msf = -inf, meh = 0, s = 0; +int kadane(const vector<int> &v, int &start, int &end) { + start = end = 0; + int msf = -inf, meh = 0, s = 0; - for (int i = 0; i < v.size(); ++i) { - meh += v[i]; + for (int i = 0; i < v.size(); ++i) { + meh += v[i]; - if (msf < meh) { - msf = meh; - start = s, end = i; - } - - if (meh < 0) { - meh = 0; - s = i + 1; - } + if (msf < meh) { + msf = meh; + start = s, end = i; } - return msf; + if (meh < 0) { + meh = 0; + s = i + 1; + } } -}; + + return msf; +} diff --git a/algorithms/paradigm/lis.cpp b/algorithms/paradigm/lis.cpp index 281adfcca41fe9b69db96a91a83971a214d87305..821903d81f97d21d031041ad31834ba83ff77548 100644 --- a/algorithms/paradigm/lis.cpp +++ b/algorithms/paradigm/lis.cpp @@ -3,18 +3,16 @@ /// Time: O(n^2) /// Space: O(n) -struct LIS { - int run(vector<int> v) { - vector<int> lis(v.size()); lis[0] = 1; +int lis(vector<int> v) { + vector<int> lis(v.size()); lis[0] = 1; - for (int i = 1; i < v.size(); ++i) { - lis[i] = 1; + for (int i = 1; i < v.size(); ++i) { + lis[i] = 1; - for (int j = 0; j < i; ++j) - if (v[i] > v[j] && lis[i] < lis[j] + 1) - lis[i] = lis[j] + 1; - } - - return *max_element(all(lis)); + for (int j = 0; j < i; ++j) + if (v[i] > v[j] && lis[i] < lis[j] + 1) + lis[i] = lis[j] + 1; } -}; + + return *max_element(all(lis)); +} diff --git a/algorithms/paradigm/longest_common_subsequence.cpp b/algorithms/paradigm/longest_common_subsequence.cpp index 9bcba82e948af1391e3534bba92602a885572709..acffd3895d7b91ada8d1f590f0efb37b63976f95 100644 --- a/algorithms/paradigm/longest_common_subsequence.cpp +++ b/algorithms/paradigm/longest_common_subsequence.cpp @@ -5,36 +5,34 @@ int dp[MAX][MAX]; -struct LCS { - string run(string a, string b) { - for (int i = 0; i <= a.size(); ++i) { - for (int j = 0; j <= b.size(); ++j) { - if (i == 0 || j == 0) - dp[i][j] = 0; - else if (a[i - 1] == b[j - 1]) - dp[i][j] = dp[i - 1][j - 1] + 1; - else - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); - } +string lcs(string a, string b) { + for (int i = 0; i <= a.size(); ++i) { + for (int j = 0; j <= b.size(); ++j) { + if (i == 0 || j == 0) + dp[i][j] = 0; + else if (a[i - 1] == b[j - 1]) + dp[i][j] = dp[i - 1][j - 1] + 1; + else + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } + } - // The size is already at dp[n][m], now the common - // subsequence is retrieved: - - int idx = dp[a.size()][b.size()]; - string ans(idx, ' '); + // The size is already at dp[n][m], now the common + // subsequence is retrieved: - int i = a.size(), j = b.size(); - while (i > 0 && j > 0) { - if (a[i - 1] == b[ j - 1]) { - ans[idx - 1] = a[i - 1]; - i--, j--, idx--; - } else if (dp[i - 1][j] > dp[i][j - 1]) - i--; - else - j--; - } + int idx = dp[a.size()][b.size()]; + string ans(idx, ' '); - return ans; + int i = a.size(), j = b.size(); + while (i > 0 && j > 0) { + if (a[i - 1] == b[ j - 1]) { + ans[idx - 1] = a[i - 1]; + i--, j--, idx--; + } else if (dp[i - 1][j] > dp[i][j - 1]) + i--; + else + j--; } -}; + + return ans; +} diff --git a/algorithms/paradigm/ternary_search.cpp b/algorithms/paradigm/ternary_search.cpp index 54372a96322c8c5cd1bc764b34bdd50a25401385..a687284e3c0b4225e0defb745e3fb45cd651f68c 100644 --- a/algorithms/paradigm/ternary_search.cpp +++ b/algorithms/paradigm/ternary_search.cpp @@ -3,31 +3,28 @@ /// Time: O(log n) /// Space: O(1) -struct TernarySearch { +// Unimodal function +double f(double x) { + return x * x; +} - // Unimodal function - double f(double x) { - return x * x; - } - - double run(double l, double r) { - double rt, lt; +double ternary_search(double l, double r) { + double rt, lt; - for (int i = 0; i < 500; ++i) { - if (fabs(r - l) < EPS) - return (l + r) / 2.0; + for (int i = 0; i < 500; ++i) { + if (fabs(r - l) < EPS) + return (l + r) / 2.0; - lt = (r - l) / 3.0 + l; - rt = ((r - l) * 2.0) / 3.0 + l; + lt = (r - l) / 3.0 + l; + rt = ((r - l) * 2.0) / 3.0 + l; - // '<' for minimum of f, - // '>' for maximum of f - if (f(lt) < f(rt)) - l = lt; - else - r = rt; - } - - return (l + r) / 2.0; + // '<' for minimum of f, + // '>' for maximum of f + if (f(lt) < f(rt)) + l = lt; + else + r = rt; } -}; + + return (l + r) / 2.0; +} diff --git a/algorithms/string/z-function.cpp b/algorithms/string/z-function.cpp index 593c054358018f9041aa01492cdc06d1b0cecd62..c1e6c789b7dc83e3ebe921a1debfd60e8d745284 100644 --- a/algorithms/string/z-function.cpp +++ b/algorithms/string/z-function.cpp @@ -3,25 +3,23 @@ /// Time: O(n) /// Space: O(n) -struct ZFunction { - vector<int> run(string s) { - int n = (int) s.length(); - vector<int> z(n); +vector<int> z_function(string s) { + int n = (int) s.length(); + vector<int> z(n); - int l = 0, r = 0; - for (int i = 1; i < n; ++i) { - if (i <= r) - z[i] = min(r - i + 1, z[i - l]); + int l = 0, r = 0; + for (int i = 1; i < n; ++i) { + if (i <= r) + z[i] = min(r - i + 1, z[i - l]); - while (i + z[i] < n && s[z[i]] == s[i + z[i]]) - z[i]++; + while (i + z[i] < n && s[z[i]] == s[i + z[i]]) + z[i]++; - if (i + z[i] - 1 > r) { - l = i; - r = i + z[i] - 1; - } + if (i + z[i] - 1 > r) { + l = i; + r = i + z[i] - 1; } - - return z; } -}; + + return z; +} diff --git a/caderno.pdf b/caderno.pdf index f9ce52fea430d4dc1a24f210c59ff867c4b99e5e..36941c4bd14d17f3e797b3d264b95d3873ddb0fa 100644 Binary files a/caderno.pdf and b/caderno.pdf differ