MathIntermediate

Euler's Totient Function

Key Points

  • Euler's Totient Function counts how many integers from 1 to n are coprime with n.
  • It satisfies the product formula = n \left(1 - \frac{1}{p}\right) over the distinct prime divisors p of n.
  • φ is multiplicative: if gcd(a, b) = 1 then = which lets you compute it from prime powers.
  • For a prime power , = - , meaning you remove multiples of p from the total.
  • A fundamental identity is = n, which connects φ to divisor sums and Farey sequences.
  • Efficient computation for a single n uses trial division up to , while computing all φ up to N uses a sieve.
  • Euler's theorem 1 \pmod m (when gcd(a, m) = 1) enables modular inverses and exponent reductions.
  • In contests, combine sieves and multiplicativity to handle many queries and number-theory transforms efficiently.

Prerequisites

  • Prime numbers and prime factorizationφ(n) is defined via the prime factorization of n and uses distinct prime divisors.
  • Greatest common divisor (gcd) and Euclidean algorithmThe definition of φ counts integers coprime to n, which relies on gcd.
  • Modular arithmetic and congruencesEuler's theorem and applications of φ work in modular arithmetic settings.
  • Sieve of EratosthenesEfficiently computing φ for ranges requires sieve techniques to find primes or SPF.
  • Time and space complexity analysisChoosing between trial division, SPF sieve, or linear sieve depends on complexity trade-offs.

Detailed Explanation

Tap terms for definitions

01Overview

Euler's Totient Function, denoted φ(n), measures how many numbers from 1 up to n share no common factor with n other than 1. In other words, it counts the integers that are coprime to n. This function is central in number theory and has powerful algebraic and algorithmic properties. Two of its most important features are multiplicativity—φ(ab) = φ(a)φ(b) when a and b are coprime—and a clean formula in terms of the prime factorization of n: φ(n) = n times the product over distinct primes p dividing n of (1 − 1/p). These facts make φ fast to compute once you know the prime factors of n. The totient function appears in many areas: it describes the size of the unit group modulo n, it underpins Euler's theorem (a generalization of Fermat's little theorem), and it counts terms in Farey sequences. In algorithmic settings like competitive programming, we often need φ for all numbers up to a limit N, which can be computed by a sieve in nearly linear time, or we need φ for many queries, which can be handled using a precomputed smallest-prime-factor array. Understanding φ helps with modular arithmetic, counting coprime pairs, and solving problems involving cyclic structures and inverses.

02Intuition & Analogies

Imagine you invite all integers from 1 to n to a party, but the door policy says, "Only those who don't share any common 'habits' (prime factors) with n can enter." If n = 12, the 'habits' are the prime factors 2 and 3. Anyone who is a multiple of 2 or 3 is turned away. The ones allowed in are 1, 5, 7, and 11—exactly four guests—so φ(12) = 4. This is precisely what the product formula does: from the total n, it removes the 1/p fraction for each prime p dividing n, just like marking off all multiples of those primes. Another way to feel it is to picture a clock with n positions (the residues modulo n). The positions that have an arrow back to 1 when you rotate by some number k (i.e., k has a multiplicative inverse modulo n) are exactly those where gcd(k, n) = 1. So φ(n) is counting the positions that are "rotationally unique"—they can navigate the clock without getting stuck. The multiplicativity property is like having two independent door policies: if you have two rooms with coprime capacities a and b, the number of people that pass both rooms' checks is the product of those that pass each room separately. For prime powers p^k, it's as if there's a single habit to avoid: multiples of p, so you keep p−1 out of every p next guests, leaving a fraction (1 − 1/p). Stack k copies (power) of that rule, and you get φ(p^k) = p^k − p^{k−1}. These mental models make the algebraic formulas feel natural rather than mysterious.

03Formal Definition

Euler's Totient Function is defined by \((n) = \). It is a multiplicative arithmetic function, meaning that if \((a, b) = 1\) then \((ab) = (a)(b)\). For prime powers, one has \(() = - \left(1 - \frac{1}{p}\right)\). Consequently, for general n with prime factorization \(n = p_\), the totient is given by the product formula \((n) = n \left(1 - \frac{1}{p_i}\right)\). Another key identity is the divisor-sum relation \( (d) = n\), which expresses that φ is the Dirichlet convolution inverse of the constant-one function with the identity function; equivalently, \( = * \), where \(\) is the Möbius function and \((n) = n\). In group-theoretic terms, \((n)\) equals the order of the multiplicative group of units modulo n, \(\left(/n\mathbb{Z}\right)^{}\). Euler's theorem states that when \((a, n) = 1\), \( 1 \), a generalization of Fermat's little theorem when n is prime.

04When to Use

Use φ(n) whenever you need to count or characterize numbers coprime to n, especially in modular arithmetic. Typical scenarios include: (1) Computing modular inverses modulo a composite m via Euler's theorem, by raising to the power φ(m)−1 when gcd(a, m) = 1. (2) Reducing huge exponents in modular exponentiation when the base is coprime to the modulus, since exponents can be taken modulo φ(m). (3) Counting reduced fractions with bounded denominators, via Farey sequences with length (|F_N| = 1 + \sum_{n=1}^{N} \varphi(n)). (4) Summing over coprime pairs, lattice-visibility problems, and problems that ask for the number of generators in cyclic groups, which often involve φ. (5) Preprocessing for number-theoretic transforms and multiplicative convolutions, where φ and related functions (μ, τ, σ) frequently appear. Algorithmically: (a) For a single n up to around 10^{12}, trial division up to \sqrt{n} is usually fast enough. (b) For all values up to N (e.g., N ≤ 10^7 or 10^8), use a sieve (linear or Euler sieve) to compute φ[1..N]. (c) For many queries with n ≤ MAXV, precompute smallest prime factors (SPF) and use the product formula per query, giving near O(log n) per query.

⚠️Common Mistakes

Common pitfalls include: (1) Forgetting that φ is only multiplicative for coprime arguments; φ(ab) ≠ φ(a)φ(b) in general unless gcd(a, b) = 1. Always check coprimality before using multiplicativity. (2) Misapplying Euler's theorem when gcd(a, m) ≠ 1; a^{φ(m)} ≡ 1 (mod m) only holds when a and m are coprime. For modular inverses, also ensure gcd(a, m) = 1. (3) Double-subtracting primes in the product formula: multiply by (1 − 1/p) once per distinct prime factor, not per prime power. (4) Overflows in intermediate products when n is large; use 64-bit integers (long long) and cast before multiplications, or use built-in big integer libraries if needed. (5) Inefficient factorization: trial dividing by every integer up to n is far too slow; stop at \sqrt{n} and handle the leftover prime. (6) In sieves, failing to initialize φ[1] = 1 and mishandling composites can produce off-by-one or zero values. (7) Mixing up identities: \sum_{d|n} φ(d) = n is not the same as \sum_{d|n} d = something; only φ sums to n. (8) Assuming φ(n) is even always; φ(n) is even for n > 2, but φ(1) = 1 and φ(2) = 1 are exceptions.

Key Formulas

Definition of Totient

Explanation: counts the integers between 1 and n that share no common factor with n. This is the foundational meaning of the function.

Prime Power Formula

Explanation: For a number that is a power of a single prime, we exclude multiples of p. Exactly a 1/p fraction are excluded from numbers.

Product Over Distinct Primes

Explanation: Multiplying by (1 − 1/p) once for each distinct prime divisor p of n removes all multiples of those primes from the count.

Divisor Sum Identity

Explanation: Summing over all divisors d of n yields n. This reflects that φ is the Dirichlet convolution of the Möbius function with the identity function.

Möbius Inversion Relation

Explanation: φ is the convolution of the Möbius function μ with the identity function id(n) = n. This can be inverted to derive various identities.

Euler's Theorem

Explanation: When a and m are coprime, raising a to the power yields 1 modulo m. This generalizes Fermat's little theorem and is key for modular inverses.

Inverse via Totient

Explanation: The modular inverse of a modulo m can be computed by exponentiation using − 1 when a and m are coprime.

Farey Sequence Length

Explanation: The number of reduced fractions between 0 and 1 with denominators up to N equals 1 plus the sum of totients up to N.

Average Order of Totient Sum

Explanation: As n grows, the sum of up to n behaves like (3/ . This gives an approximate growth rate for cumulative totients.

Multiplicativity

Explanation: φ respects multiplication for coprime inputs. This allows computation from prime-power factors and greatly speeds up algorithms.

Complexity Analysis

There are several practical strategies to compute 1) Single n by trial division: Factor n by testing divisors up to . Each time you find a prime factor p, divide n repeatedly by p and apply the update × (1 − 1/p). The time complexity is O() division steps in the worst case (when n is prime or has large prime factors). The space usage is O(1). This is fast for n up to about 10^{12} in typical contests with a few test cases. 2) Sieve for all φ up to N (linear/Euler sieve): Maintain a list of primes and compute φ for each composite exactly once. The linear sieve runs in O(N) time with O(N) memory, while the classical Eratosthenes-style multiplicative sieve runs in O(N N). Either approach is suitable up to N ≈ 10^7–10^8 depending on memory and time limits. Space is O(N) for arrays of size N. 3) Smallest Prime Factor (SPF) sieve for many queries: Precompute SPF for all numbers up to MAXV in O(MAXV) time and O(MAXV) space. Then answer each query in O((n)) time where (n) is the number of distinct prime factors ( n), by reconstructing the distinct primes from the SPF chain and applying the product formula. This yields near-constant time per query in practice. 4) Applications like Farey sequence length or counting coprime pairs often need prefix sums S(N) = After computing φ by sieve, a single O(N) pass forms the prefix, giving O(1) per query for ranges. Overall, choose trial division for one-off large n, sieves for dense ranges, and SPF for many random queries within a bound.

Code Examples

Compute φ(n) by prime factorization (trial division up to sqrt(n))
1#include <bits/stdc++.h>
2using namespace std;
3
4// Computes Euler's Totient phi(n) by trial division.
5// Works well for single n up to about 1e12 in typical time limits.
6long long phi_trial_division(long long n) {
7 if (n == 0) return 0; // conventionally undefined, but return 0 here
8 long long result = n; // start with n and apply multiplicative updates
9 // Handle factor 2 separately for small optimization
10 if ((n & 1LL) == 0) {
11 result = result / 2; // multiply by (1 - 1/2)
12 while ((n & 1LL) == 0) n >>= 1; // remove all factors of 2
13 }
14 // Try odd factors up to sqrt(n)
15 for (long long p = 3; p * p <= n; p += 2) {
16 if (n % p == 0) {
17 result = result / p * (p - 1); // multiply by (1 - 1/p)
18 while (n % p == 0) n /= p; // remove all factors of p
19 }
20 }
21 // If n > 1 now, it's a prime factor larger than sqrt(original n)
22 if (n > 1) {
23 result = result / n * (n - 1);
24 }
25 return result;
26}
27
28int main() {
29 ios::sync_with_stdio(false);
30 cin.tie(nullptr);
31
32 long long n;
33 if (!(cin >> n)) return 0;
34 cout << phi_trial_division(n) << "\n";
35 return 0;
36}
37

This program factors n by trial division up to sqrt(n). For each distinct prime factor p found, it multiplies the running result by (1 − 1/p) using integer-safe operations result = result/p*(p−1). If there is a leftover prime greater than sqrt(n), it applies the update once more. This directly implements φ(n) = n \prod_{p|n} (1 − 1/p).

Time: O(\sqrt{n}) in the worst caseSpace: O(1)
Linear sieve to compute φ[1..N] and Farey sequence length
1#include <bits/stdc++.h>
2using namespace std;
3
4// Linear (Euler) sieve to compute phi[1..N] in O(N) time.
5// Also computes the Farey sequence length |F_N| = 1 + sum_{k=1}^N phi(k).
6
7int main() {
8 ios::sync_with_stdio(false);
9 cin.tie(nullptr);
10
11 int N; // e.g., up to 1e7 depending on memory/time limits
12 if (!(cin >> N)) return 0;
13
14 vector<int> phi(N + 1);
15 vector<int> primes;
16 vector<bool> is_composite(N + 1, false);
17
18 phi[0] = 0;
19 if (N >= 1) phi[1] = 1;
20
21 for (int i = 2; i <= N; ++i) {
22 if (!is_composite[i]) {
23 primes.push_back(i);
24 phi[i] = i - 1; // phi(p) = p - 1 for prime p
25 }
26 for (int p : primes) {
27 long long v = 1LL * i * p;
28 if (v > N) break;
29 is_composite[(int)v] = true;
30 if (i % p == 0) {
31 // p divides i: phi(i * p) = phi(i) * p
32 phi[(int)v] = phi[i] * p;
33 break; // crucial for linear complexity
34 } else {
35 // p does not divide i: phi(i * p) = phi(i) * (p - 1)
36 phi[(int)v] = phi[i] * (p - 1);
37 }
38 }
39 }
40
41 // Compute Farey sequence length |F_N| = 1 + sum_{k=1}^N phi(k)
42 long long farey_len = 1; // starts with 1
43 for (int k = 1; k <= N; ++k) farey_len += phi[k];
44
45 // Output a few sample values and the Farey length
46 cout << "phi(1..min(N,10)): ";
47 for (int i = 1; i <= min(N, 10); ++i) cout << phi[i] << (i == min(N, 10) ? '\n' : ' ');
48 cout << "|F_" << N << "| = " << farey_len << "\n";
49 return 0;
50}
51

This uses the linear (Euler) sieve to compute φ for all numbers up to N. Each composite is visited exactly once with its least prime factor, ensuring O(N) time. Then it computes the Farey sequence length using the identity |F_N| = 1 + ∑_{k=1}^N φ(k).

Time: O(N)Space: O(N)
Answer many φ(n) queries quickly using a precomputed SPF array
1#include <bits/stdc++.h>
2using namespace std;
3
4// Precompute SPF (smallest prime factor) up to MAXV and answer Q totient queries.
5// For each query n, reconstruct its distinct prime factors using SPF and apply
6// phi(n) = n * product_{p | n} (1 - 1/p).
7
8struct SPF {
9 int MAXV;
10 vector<int> spf; // smallest prime factor for each x
11 explicit SPF(int maxv): MAXV(maxv), spf(maxv + 1) {
12 build();
13 }
14 void build() {
15 iota(spf.begin(), spf.end(), 0);
16 for (int i = 2; 1LL * i * i <= MAXV; ++i) {
17 if (spf[i] == i) { // i is prime
18 for (long long j = 1LL * i * i; j <= MAXV; j += i) {
19 if (spf[(int)j] == (int)j) spf[(int)j] = i;
20 }
21 }
22 }
23 }
24 // Factorization returning distinct primes dividing n
25 vector<int> distinct_primes(int n) const {
26 vector<int> ps;
27 while (n > 1) {
28 int p = spf[n];
29 ps.push_back(p);
30 while (n % p == 0) n /= p;
31 }
32 return ps;
33 }
34};
35
36long long phi_from_distinct_primes(long long n, const vector<int>& primes) {
37 long long res = n;
38 for (int p : primes) {
39 res = (res / p) * (p - 1);
40 }
41 return res;
42}
43
44int main() {
45 ios::sync_with_stdio(false);
46 cin.tie(nullptr);
47
48 int MAXV, Q;
49 if (!(cin >> MAXV >> Q)) return 0;
50 SPF spf(MAXV);
51
52 while (Q--) {
53 int n; cin >> n;
54 if (n == 0) { cout << 0 << '\n'; continue; }
55 if (n == 1) { cout << 1 << '\n'; continue; }
56 auto ps = spf.distinct_primes(n);
57 cout << phi_from_distinct_primes(n, ps) << '\n';
58 }
59 return 0;
60}
61

An SPF sieve precomputes the smallest prime factor for each number up to MAXV. Each query factors n in O(number of prime factors) time by walking down via SPF and collecting distinct primes. Applying φ(n) = n ∏_{p|n} (1 − 1/p) then yields the answer quickly. This is efficient for many queries with bounded n.

Time: Preprocessing O(MAXV), per query O(\omega(n))Space: O(MAXV)
Compute modular inverse using Euler's theorem and φ(m)
1#include <bits/stdc++.h>
2using namespace std;
3
4long long phi_trial_division(long long n) {
5 if (n == 0) return 0;
6 long long result = n;
7 if ((n & 1LL) == 0) {
8 result = result / 2;
9 while ((n & 1LL) == 0) n >>= 1;
10 }
11 for (long long p = 3; p * p <= n; p += 2) {
12 if (n % p == 0) {
13 result = result / p * (p - 1);
14 while (n % p == 0) n /= p;
15 }
16 }
17 if (n > 1) result = result / n * (n - 1);
18 return result;
19}
20
21long long mod_mul(long long a, long long b, long long m) {
22 // Safe multiplication for 64-bit using __int128
23 __int128 r = ( __int128)a * b % m;
24 return (long long)r;
25}
26
27long long mod_pow(long long a, long long e, long long m) {
28 long long r = 1 % m;
29 a %= m;
30 while (e > 0) {
31 if (e & 1) r = mod_mul(r, a, m);
32 a = mod_mul(a, a, m);
33 e >>= 1;
34 }
35 return r;
36}
37
38// Returns modular inverse of a modulo m if gcd(a,m)=1; otherwise returns -1.
39long long mod_inverse_totient(long long a, long long m) {
40 long long g = std::gcd(a, m);
41 if (g != 1) return -1; // inverse does not exist
42 long long ph = phi_trial_division(m);
43 // Euler: a^{phi(m)} ≡ 1 (mod m) => a^{phi(m)-1} is the inverse
44 return mod_pow((a % m + m) % m, ph - 1, m);
45}
46
47int main() {
48 ios::sync_with_stdio(false);
49 cin.tie(nullptr);
50
51 long long a, m;
52 if (!(cin >> a >> m)) return 0;
53 long long inv = mod_inverse_totient(a, m);
54 if (inv == -1) cout << "No inverse\n";
55 else cout << inv << "\n";
56 return 0;
57}
58

This program computes the modular inverse of a modulo m using Euler's theorem: if gcd(a, m) = 1, then a^{φ(m)} ≡ 1 (mod m), hence a^{φ(m)−1} is the inverse. It first computes φ(m) by trial division, then performs fast modular exponentiation. It correctly reports when the inverse does not exist.

Time: O(\sqrt{m} + \log m) for one querySpace: O(1)