Skip to content

Commit 65de424

Browse files
Add Tutorial for LOJ-1161 Extreme GCD (en) (#439)
* Created en.md for LOJ-1161 * Added tutorial for LOJ-1161 * Update en.md * Update en.md fixed Indentation.
1 parent b8ffbf7 commit 65de424

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

1161/en.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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

Comments
 (0)