All Euler problems
Project Euler

Minimum Values of the Carmichael Function

The Carmichael function lambda(n) is the smallest positive integer m such that a^m equiv 1 (mod n) for every integer a coprime to n. Define f(N) = |left{n: 1 <= n <= N, lambda(n) = lambda(n+1)right...

Source sync Apr 19, 2026
Problem #0533
Level Level 26
Solved By 391
Languages C++, Python
Answer 789453601
Length 266 words
number_theorymodular_arithmeticoptimization

Problem Statement

This archive keeps the full statement, math, and original media on the page.

The Carmichael function \(\lambda (n)\) is defined as the smallest positive integer \(m\) such that \(a^m = 1\) modulo \(n\) for all integers \(a\) coprime with \(n\).

For example \(\lambda (8) = 2\) and \(\lambda (240) = 4\).

Define \(L(n)\) as the smallest positive integer \(m\) such that \(\lambda (k) \ge n\) for all \(k \ge m\).

For example, \(L(6) = 241\) and \(L(100) = 20\,174\,525\,281\).

Find \(L(20\,000\,000)\). Give the last \(9\) digits of your answer.

Problem 533: Minimum Values of the Carmichael Function

Mathematical Foundation

Theorem 1 (Carmichael Function Decomposition). For n=i=1rpiain = \prod_{i=1}^{r} p_i^{a_i},

λ(n)=lcm(λ(p1a1),λ(p2a2),,λ(prar)),\lambda(n) = \operatorname{lcm}\bigl(\lambda(p_1^{a_1}),\, \lambda(p_2^{a_2}),\, \ldots,\, \lambda(p_r^{a_r})\bigr),

where the local values are:

  • λ(1)=1\lambda(1) = 1, λ(2)=1\lambda(2) = 1, λ(4)=2\lambda(4) = 2,
  • λ(2k)=2k2\lambda(2^k) = 2^{k-2} for k3k \ge 3,
  • λ(pk)=pk1(p1)\lambda(p^k) = p^{k-1}(p - 1) for odd prime pp.

Proof. By the Chinese Remainder Theorem, (Z/nZ)×i=1r(Z/piaiZ)×(\mathbb{Z}/n\mathbb{Z})^\times \cong \prod_{i=1}^{r} (\mathbb{Z}/p_i^{a_i}\mathbb{Z})^\times. The exponent (i.e., the least universal order) of a direct product of groups equals the LCM of the exponents of the factors. It remains to determine the exponent of each factor:

  • For odd pp, (Z/pkZ)×(\mathbb{Z}/p^k\mathbb{Z})^\times is cyclic of order φ(pk)=pk1(p1)\varphi(p^k) = p^{k-1}(p-1), so its exponent is pk1(p1)p^{k-1}(p-1).
  • For p=2p = 2: (Z/2Z)×={1}(\mathbb{Z}/2\mathbb{Z})^\times = \{1\} has exponent 11; (Z/4Z)×C2(\mathbb{Z}/4\mathbb{Z})^\times \cong C_2 has exponent 22; for k3k \ge 3, (Z/2kZ)×C2×C2k2(\mathbb{Z}/2^k\mathbb{Z})^\times \cong C_2 \times C_{2^{k-2}} has exponent 2k22^{k-2}.

The last claim follows because 1-1 has order 22 and 55 has order 2k22^{k-2} modulo 2k2^k (provable by induction on kk using the binomial theorem: 52k3=(1+4)2k31+2k1(mod2k)5^{2^{k-3}} = (1+4)^{2^{k-3}} \equiv 1 + 2^{k-1} \pmod{2^k} for k4k \ge 4, which is not 11, but 52k21(mod2k)5^{2^{k-2}} \equiv 1 \pmod{2^k}). \square

Lemma 1 (SPF-Based Factoring). Using a smallest-prime-factor sieve, any integer nNn \le N can be fully factored in O(ω(n))O(\omega(n)) time, where ω(n)\omega(n) is the number of distinct prime factors.

Proof. The sieve stores spf(n)\operatorname{spf}(n) for each nNn \le N in O(N)O(N) time (linear sieve). To factor nn, repeatedly extract p=spf(n)p = \operatorname{spf}(n) and divide nn by pp until n=1n = 1. Each step reduces nn by at least one prime factor, giving O(ω(n))O(\omega(n)) steps. \square

Editorial

Count n <= N where lambda(n) = lambda(n+1). lambda(n) = lcm of lambda(p^k) over prime powers p^k || n, where: lambda(2) = 1, lambda(4) = 2, lambda(2^k) = 2^{k-2} for k >= 3 lambda(p^k) = p^{k-1}(p-1) for odd prime p Algorithm: SPF sieve + per-element lambda computation.

Pseudocode

    spf[1..N+1] = linear_sieve(N + 1) // smallest prime factor

        result = 1
        While n > 1:
            p = spf[n]
            pk = 1
            While n mod p == 0:
                n = n / p
                pk = pk * p
            local = pk / p * (p - 1) // phi(p^k)
            If p == 2 and pk >= 8 then
                local = local / 2 // lambda(2^k) = 2^{k-2}
            result = lcm(result, local)
        Return result

    count = 0
    prev = LAMBDA(1)
    For n from 1 to N:
        curr = LAMBDA(n + 1)
        If prev == curr then
            count += 1
        prev = curr
    Return count

Complexity Analysis

  • Time: The linear sieve runs in O(N)O(N). Computing λ(n)\lambda(n) for each nn takes amortized O(1)O(1) per integer (since nNω(n)=O(NloglogN)\sum_{n \le N} \omega(n) = O(N \log \log N)). Comparing consecutive values is O(1)O(1). Total: O(NloglogN)O(N \log \log N).
  • Space: O(N)O(N) for the SPF array plus O(1)O(1) working space per λ\lambda computation.

For N=108N = 10^8: several seconds in C++, feasible in optimized code.

Answer

789453601\boxed{789453601}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_533/solution.cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*
 * Problem 533: Minimum Values of the Carmichael Function
 *
 * Count n in [1, N] where lambda(n) = lambda(n+1).
 *
 * lambda(n) = lcm of lambda(p^k) over prime powers p^k || n.
 * lambda(p^k) = phi(p^k) for odd p, special rules for p=2.
 *
 * Algorithm: SPF sieve, compute lambda per element, compare consecutive.
 * Time: O(N log log N).  Space: O(N).
 */

const int N = 100000001; // 10^8 + 1

int spf[N + 1];

void build_spf() {
    for (int i = 0; i <= N; i++) spf[i] = i;
    for (int i = 2; (ll)i * i <= N; i++) {
        if (spf[i] == i) {
            for (int j = i * i; j <= N; j += i) {
                if (spf[j] == j) spf[j] = i;
            }
        }
    }
}

ll compute_lambda(int n) {
    if (n <= 1) return 1;
    ll result = 1;
    while (n > 1) {
        int p = spf[n];
        ll pk = 1;
        int k = 0;
        while (n % p == 0) {
            n /= p;
            pk *= p;
            k++;
        }
        ll local;
        if (p == 2) {
            if (k == 1) local = 1;
            else if (k == 2) local = 2;
            else local = pk / 4;  // 2^{k-2}
        } else {
            local = pk / p * (p - 1);  // phi(p^k)
        }
        result = result / __gcd(result, local) * local;  // lcm
    }
    return result;
}

int main() {
    build_spf();

    int count = 0;
    ll prev = compute_lambda(1);
    for (int n = 2; n <= N; n++) {
        ll curr = compute_lambda(n);
        if (prev == curr && n - 1 <= N - 1) {
            count++;
        }
        prev = curr;
    }

    cout << count << endl;

    return 0;
}