|
| 1 | + |
| 2 | +#include <bits/stdc++.h> |
| 3 | + |
| 4 | +using namespace std; |
| 5 | + |
| 6 | +const int N = 1010; |
| 7 | +const int MOD = 1e9 + 7; |
| 8 | + |
| 9 | +// Returns the greatest common divisors (GCD) of the given two numbers. |
| 10 | +// Worst case when (a, b) are two consecutive Fibonacci numbers. |
| 11 | +// O(log(n)) |
| 12 | +int gcd(int a, int b) { |
| 13 | + while (b) { |
| 14 | + int tmp = a % b; |
| 15 | + a = b; |
| 16 | + b = tmp; |
| 17 | + } |
| 18 | + return a; |
| 19 | +} |
| 20 | + |
| 21 | +// Returns the greatest common divisors (GCD) of the given two numbers recursively. |
| 22 | +// Worst case when (a, b) are two consecutive Fibonacci numbers. |
| 23 | +// O(log(n)) |
| 24 | +int gcd_rec(int a, int b) { |
| 25 | + return b == 0 ? a : gcd_rec(b, a % b); |
| 26 | +} |
| 27 | + |
| 28 | +// Returns the least common multiple (LCM) of the given two numbers. |
| 29 | +// O(GCD(a, b)) = O(log(n)) |
| 30 | +int lcm(int a, int b) { |
| 31 | + return a / gcd(a, b) * b; |
| 32 | +} |
| 33 | + |
| 34 | +// Returns the Bezout's coefficients of the smallest positive linear combination of a and b |
| 35 | +// using the extended Euclidean algorithm. |
| 36 | +// (i.e. GCD(a, b) = s.a + t.b). |
| 37 | +// O(GCD(a, b)) = O(log(n)) |
| 38 | +pair<int, int> extendedEuclid(int a, int b) { |
| 39 | + if (b == 0) { |
| 40 | + return { 1, 0 }; |
| 41 | + } |
| 42 | + |
| 43 | + pair<int, int> p = extendedEuclid(b, a % b); |
| 44 | + |
| 45 | + int s = p.first; |
| 46 | + int t = p.second; |
| 47 | + |
| 48 | + return { t, s - t * (a / b) }; |
| 49 | +} |
| 50 | + |
| 51 | +// Returns ((base^exp) mod m) using iterative fast power algorithm |
| 52 | +// Note that if (base=0, exp=0) is passed to the function it will return 1. |
| 53 | +// O(log(exp)) |
| 54 | +int power(int base, int exp, int mod) { |
| 55 | + int ans = 1; |
| 56 | + base %= mod; |
| 57 | + |
| 58 | + while (exp > 0) { |
| 59 | + if (exp & 1) ans = (ans * base) % mod; |
| 60 | + exp >>= 1; |
| 61 | + base = (base * base) % mod; |
| 62 | + } |
| 63 | + |
| 64 | + return ans; |
| 65 | +} |
| 66 | + |
| 67 | +// Returns ((base^exp) mod m) using recursive fast power algorithm. |
| 68 | +// Note that if (base=0, exp=0) is passed to the function it will return 1. |
| 69 | +// O(log(exp)) |
| 70 | +int power_rec(int base, int exp, int mod) { |
| 71 | + if (exp == 0) { |
| 72 | + return 1; |
| 73 | + } |
| 74 | + |
| 75 | + int p = power_rec((base * base) % mod, exp >> 1, mod); |
| 76 | + |
| 77 | + return (exp & 1) ? (p * base) % mod : p; |
| 78 | +} |
| 79 | + |
| 80 | +// Returns the modular inverse of the given number modulo m. |
| 81 | +// (i.e. (a * mod_inverse(a)) == 1 (mod m)). |
| 82 | +// Note that the function works correctly only if m is a prime number. |
| 83 | +// O(log(m)) |
| 84 | +int modInverse(int a, int m) { |
| 85 | + return power(a, m - 2, m); |
| 86 | +} |
| 87 | + |
| 88 | +// Returns n choose r. |
| 89 | +// (i.e. The number of distinct sets of size k chosen from n-items). |
| 90 | +// Note that C(n, r) = C(n, n - r) |
| 91 | +// So call the function with nCr(n, min(r, n-r)) for better performance. |
| 92 | +// O(r) |
| 93 | +int nCr(int n, int r) { |
| 94 | + if (n < r) |
| 95 | + return 0; |
| 96 | + |
| 97 | + if (r == 0) |
| 98 | + return 1; |
| 99 | + |
| 100 | + return n * nCr(n - 1, r - 1) / r; |
| 101 | +} |
| 102 | + |
| 103 | +// Builds Pascal's triangle of size n for computing the combinations. |
| 104 | +// After calling this function, comb[n][r] will be equals to nCr. |
| 105 | +// O(n^2) |
| 106 | +int comb[N][N]; |
| 107 | +void buildPT(int n) { |
| 108 | + for (int i = comb[0][0] = 1; i <= n; ++i) |
| 109 | + for (int j = comb[i][0] = 1; j <= i; ++j) |
| 110 | + comb[i][j] = (comb[i - 1][j] + comb[i - 1][j - 1]) % MOD; |
| 111 | +} |
| 112 | + |
| 113 | +// Returns whether the given number is prime or not. |
| 114 | +// O(sqrt(n)) |
| 115 | +bool isPrime(int n) { |
| 116 | + if (n < 2) |
| 117 | + return 0; |
| 118 | + if (n % 2 == 0) |
| 119 | + return (n == 2); |
| 120 | + for (int i = 3; i * i <= n; i += 2) |
| 121 | + if (n % i == 0) |
| 122 | + return 0; |
| 123 | + return 1; |
| 124 | +} |
| 125 | + |
| 126 | +// Generates all the prime numbers from 1 to the given number n |
| 127 | +// using Sieve of Eratosthenes' algorithm. |
| 128 | +// After calling this function, prime[i] will be equal 1 if i is prime, 0 otherwise. |
| 129 | +// O(n.log(log(n))) |
| 130 | +bool prime[N]; |
| 131 | +void generatePrimes(int n) { |
| 132 | + memset(prime, true, sizeof(prime)); |
| 133 | + prime[0] = prime[1] = false; |
| 134 | + |
| 135 | + for (int i = 2; i * i <= n; ++i) { |
| 136 | + if (!prime[i]) continue; |
| 137 | + |
| 138 | + for (int j = i * i; j <= n; j += i) { |
| 139 | + prime[j] = false; |
| 140 | + } |
| 141 | + } |
| 142 | +} |
| 143 | + |
| 144 | +// Generates all the prime divisors of the numbers from 1 to n. |
| 145 | +// After calling this function, |
| 146 | +// primeDivs[i] will contains all the prime divisors of number i. |
| 147 | +// O(n.log(log(n))) |
| 148 | +vector<int> primeDivs[N]; |
| 149 | +void generatePrimeDivisors(int n) { |
| 150 | + for (int i = 2; i <= n; ++i) { |
| 151 | + if (primeDivs[i].size()) continue; |
| 152 | + |
| 153 | + for (int j = i; j <= n; j += i) { |
| 154 | + primeDivs[j].push_back(i); |
| 155 | + } |
| 156 | + } |
| 157 | +} |
| 158 | + |
| 159 | +// Returns a list of divisors of the given number. |
| 160 | +// O(sqrt(n)) |
| 161 | +vector<int> getDivisors(int n) { |
| 162 | + vector<int> divs; |
| 163 | + |
| 164 | + for (int i = 1; i * i <= n; ++i) { |
| 165 | + if (n % i == 0) { |
| 166 | + divs.push_back(i); |
| 167 | + |
| 168 | + if (i * i != n) { |
| 169 | + divs.push_back(n / i); |
| 170 | + } |
| 171 | + } |
| 172 | + } |
| 173 | + |
| 174 | + sort(divs.begin(), divs.end()); |
| 175 | + |
| 176 | + return divs; |
| 177 | +} |
| 178 | + |
| 179 | +// Generates all the divisors of the numbers from 1 to n. |
| 180 | +// After calling this function, |
| 181 | +// divs[i] will contains all the divisors of number i. |
| 182 | +// O(n.log(n)) |
| 183 | +vector<int> divs[N]; |
| 184 | +void generateDivisors(int n) { |
| 185 | + for (int i = 1; i <= n; ++i) |
| 186 | + for (int j = i; j <= n; j += i) |
| 187 | + divs[j].push_back(i); |
| 188 | +} |
0 commit comments