diff --git a/algorithms/geometry/convex_hull.cpp b/algorithms/geometry/convex_hull.cpp index 961fd505a0951cddd8d4fbb0249d96a33068d069..387467042daf4230d814b610d4e1a5fc3068a34e 100644 --- a/algorithms/geometry/convex_hull.cpp +++ b/algorithms/geometry/convex_hull.cpp @@ -3,9 +3,8 @@ /// Complexity (Time): O(n log n) /// Complexity (Space): O(n) -typedef pair<double,double> dd; - struct ConvexHull { + using dd = pair<double,double>; /// The three points are a counter-clockwise turn if cross > 0, clockwise if /// cross < 0, and collinear if cross = 0 diff --git a/algorithms/graph/centroid_decomposition.cpp b/algorithms/graph/centroid_decomposition.cpp index b6509c6c2bdf755e6fe7ebc3c0b3ded7b0f606ec..d9a34c0559eecf8f8c6d613767cce141a4583a84 100644 --- a/algorithms/graph/centroid_decomposition.cpp +++ b/algorithms/graph/centroid_decomposition.cpp @@ -6,6 +6,17 @@ // Must be a tree vector<int> graph[MAX]; +/// The Centroid Decomposition of a tree is a tree where: +/// - Its root is the centroid of the original tree. +/// - Its children are the centroid of each tree resulting from the removal +/// of the root from the original tree. +/// The result is a tree with lg(n) height, where the path from a to b in +/// the original tree can be decomposed into the path from a to lca(a,b) and +/// from lca(a,b) to b, where lca(a,b) is the lowest common ancestor of a and b +/// in the centroid decomposition. +/// This is useful because each one of the n^2 paths of the original tree is +/// the concatenation of two paths in a set of O(n lg(n)) paths from a node to +/// all its ancestors in the centroid decomposition. struct CentroidDecomposition { vector<int> par, size, marked; diff --git a/algorithms/math/euler_totient.cpp b/algorithms/math/euler_totient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f41cdff24475a365225253a313717e36f1f4d411 --- /dev/null +++ b/algorithms/math/euler_totient.cpp @@ -0,0 +1,25 @@ +/// Euler Totient (phi) +/// +/// Complexity (time): O(sqrt(n)) +/// Complexity (space): O(1) + +struct EulerTotient { + + /// Returns phi(n) (i.e. the number of relative primes less than n) + /// @param n input number + int run(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; + } + } + + if (n > 1) + result -= result / n; + + return result; + } +}; diff --git a/problems/exponial.cpp b/problems/exponial.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1564e0fc538f86bf1260fca4963b6676fe1a271d --- /dev/null +++ b/problems/exponial.cpp @@ -0,0 +1,78 @@ +#include <bits/stdc++.h> + +#define EPS 1e-6 +#define MOD 1000000007 +#define inf 0x3f3f3f3f +#define llinf 0x3f3f3f3f3f3f3f3f + +#define fi first +#define se second +#define pb push_back +#define ende '\n' + +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +#define mset(x, y) memset(&x, (y), sizeof(x)) + +using namespace std; + +using ll = long long; +using ii = pair<int,int>; + +ll phi(ll n) { + ll result = n; + + for (ll 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; + + return result; +} + +ll fast_pow(ll x, ll n, ll m) { + ll ans = 1; + + while (n) { + if (n & 1) + ans = (ans * x) % m; + + n >>= 1; + x = (x * x) % m; + } + + return ans % m; +} + +ll solve(ll n, ll m) { + if (m == 1) + return 0; + + if (n <= 5) { + if (n == 4) return 262144 % m; + else if (n == 3) return 9 % m; + else if (n == 2) return 2 % m; + else if (n == 1) return 1 % m; + else return fast_pow(5, 262144, m); + } + + // n^e % m == n^(phi(m) + e % phi(m)) mod m + ll p = phi(m); + ll e = p + solve(n - 1, p) % p; + return fast_pow(n, e, m); +} + +int main() { + ios::sync_with_stdio(0); + cin.tie(0); + + ll n, m; cin >> n >> m; + cout << solve(n, m) << ende; + + return 0; +}