|
| 1 | +# LOJ 1161 - Extreme GCD |
| 2 | + |
| 3 | +## Summary |
| 4 | +The problem is asking for the number of ways to choose four positive integers, which may or may not be distinct, from a given set of N positive integers, such that their greatest common divisor (GCD) is 1. |
| 5 | + |
| 6 | +## Prerequisite |
| 7 | +i) Basic Permutation and Combination. |
| 8 | + |
| 9 | +ii) Finding divisors of an integer N in O( $\sqrt{N}$ ) complexity. |
| 10 | + |
| 11 | +## Solution |
| 12 | +Let's generalize the problem a bit. We define: |
| 13 | + |
| 14 | +**div_cnt[i]** = how many of those N numbers have a divisor equal to **i**. |
| 15 | + |
| 16 | +**ans[k]** = number of ways choosing **4** integers from the set of N numbers such that their gcd is **equal to k**. |
| 17 | + |
| 18 | +Now in order for having gcd equal to **k** those 4 numbers must have **k** as their common divisor but not a multiple of **k** (greater than **k**) as in that case gcd will not be equal to **k** (will be a multiple of **k** greater than **k** itself). If we set **ans[k]** = **nC4**( **div_cnt[k]** ) then we would have wronged ourselvs, because **ans[k]** will going to count some selections where gcd of those 4 numbers is a multiple of **k** but not **k**. So in this scenario we have to substract all **ans[k*i]** (i > 1) from **ans[k]** so that the **ans[k]** will be the required answer. Having discussed the solution we are bound to calculate the **ans** array in decreasing order as every **ans[i]** depends on the multiples of **i**. |
| 19 | + |
| 20 | +## Complexity |
| 21 | +- Time Complexity: O(T * N * $log{_2}{N}$ ). |
| 22 | +- Memory Complexity: O(N). |
| 23 | + |
| 24 | +## Code |
| 25 | + |
| 26 | +### C++ |
| 27 | + |
| 28 | +```cpp |
| 29 | +#include <bits/stdc++.h> |
| 30 | + |
| 31 | +using namespace std; |
| 32 | + |
| 33 | + |
| 34 | +typedef long long ll; |
| 35 | + |
| 36 | + |
| 37 | +const int MAXN = 1e4; |
| 38 | + |
| 39 | +inline ll nC4(ll n) { |
| 40 | + return (n*(n-1)*(n-2)*(n-3)) / 24; |
| 41 | +} |
| 42 | + |
| 43 | +int main(int argc, const char *argv[]) { |
| 44 | + |
| 45 | + // for fast I/O |
| 46 | + ios_base::sync_with_stdio(false); |
| 47 | + cin.tie(nullptr); |
| 48 | + |
| 49 | + int t; |
| 50 | + cin >> t; |
| 51 | + |
| 52 | + for(int ts = 1; ts <= t; ++ts) { |
| 53 | + int n; |
| 54 | + cin >> n; |
| 55 | + |
| 56 | + vector <int> div_cnt(MAXN+1); |
| 57 | + for(int i = 0; i < n; ++i) { |
| 58 | + int x; |
| 59 | + cin >> x; |
| 60 | + |
| 61 | + for(int j = 1; j*j <= x; ++j) { |
| 62 | + if (x % j) { |
| 63 | + continue; |
| 64 | + } |
| 65 | + div_cnt[j]++; |
| 66 | + if (j*j != x) { |
| 67 | + div_cnt[x/j]++; |
| 68 | + } |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + vector <ll> ans(MAXN+1); |
| 73 | + for(int i = MAXN; i >= 1; --i) { |
| 74 | + ans[i] = nC4(div_cnt[i]); |
| 75 | + for(int j = i+i; j <= MAXN; j += i) { |
| 76 | + ans[i] -= ans[j]; |
| 77 | + } |
| 78 | + } |
| 79 | + |
| 80 | + cout << "Case " << ts << ": " << ans[1] << '\n'; |
| 81 | + } |
| 82 | + |
| 83 | + return 0; |
| 84 | +} |
| 85 | +``` |
0 commit comments