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 algorithm — The definition of φ counts integers coprime to n, which relies on gcd.
- →Modular arithmetic and congruences — Euler's theorem and applications of φ work in modular arithmetic settings.
- →Sieve of Eratosthenes — Efficiently computing φ for ranges requires sieve techniques to find primes or SPF.
- →Time and space complexity analysis — Choosing between trial division, SPF sieve, or linear sieve depends on complexity trade-offs.
Detailed Explanation
Tap terms for definitions01Overview
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
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
Code Examples
1 #include <bits/stdc++.h> 2 using 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. 6 long 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 28 int 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).
1 #include <bits/stdc++.h> 2 using 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 7 int 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).
1 #include <bits/stdc++.h> 2 using 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 8 struct 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 36 long 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 44 int 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.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 long 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 21 long 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 27 long 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. 39 long 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 47 int 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.