Editorial
Why is this method of computing the Euler Totient Function incorrect? We assume that all numbers less than or equal to n
are co-prime to n
. Also, the GCD of (n, something)
has to be a divisor of n
. Since we will eventually iterate over all divisors of n
, we can reduce the count of co-prime elements by 1 everytime we hit a divisor.
vector<int> compute_phi(int n) {
vector<int> phi(n + 1, 0);
for (int i = 1; i <= n; i++) {
// Assume all numbers are co-prime at first.
// We will then reduce the count every time we see its divisor.
phi[i] = i;
}
for (int i = 2; i <= n; i++) {
for (int j = i; j <= n; j += i) {
// j divides i, so reduce the divisor count by 1.
phi[j]--;
}
}
return phi;
}
Why is this method of computing the Euler Totient Function incorrect? We assume that all numbers less than or equal to n
are co-prime to n
. Note that a gcd is eventually a divisor, say d
. If gcd is d
, then gcd(n, number) = d
implies that the gcd(n/d, number/d) = 1
. Hence, all numbers that are co-prime to n/d
can be extended to create an eventual gcd of d
. Since there are phi(n/d)
such numbers, we iterate over each divisor, and remove the contribution of phi(n/d)
.
vector<int> compute_phi(int n) {
vector<int> phi(n + 1, 0);
for (int i = 1; i <= n; i++) {
// Assume all numbers are co-prime at first.
phi[i] = i;
}
for (int i = 2; i <= n; i++) {
for (int j = i; j <= n; j += i) {
phi[j] -= phi[j / i];
}
}
return phi;
}