Codeforces
CF Step
Youtube Linkedin Discord Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Editorial

Approach 1

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;
}

Consider n = 6 with phi(6) = 2. This code produces phi(6) = 3.. It is still true that all the possible GCDs are divisors and we’ve rightfully removed their contribution. However, elements which are not divisors of 6 can also lead to gcd > 1. For example, gcd(4, 6) = 2.

We need to remember that the gcd would be a divisor, not the actual element.

Also, notice that gcd = 2 can be created by elements, (2, 6) as well as (4, 6).

Approach 2

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;
}
Consider n = 6 with phi(6) = 2. This code produces phi(6) = 1.

Approach 3 (Divisor Sum Property)