All Euler problems
Project Euler

Project Euler Problem 407: Idempotents

If we calculate a^2 mod 6 for 0 <= a <= 5 we get: 0, 1, 4, 3, 4, 1. The largest value of a such that a^2 = a (mod 6) is 4. Let M(n) be the largest value of a < n such that a^2 = a (mod n). Find: Su...

Source sync Apr 19, 2026
Problem #0407
Level Level 09
Solved By 2,871
Languages C++, Python
Answer 39782849136421
Length 346 words
number_theorymodular_arithmeticbrute_force

Problem Statement

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

If we calculate \(a^2 \mod 6\) for \(0 \leq a \leq 5\) we get: \(0, 1, 4, 3, 4, 1\).

The largest value of \(a\) such that \(a^2 \equiv a \pmod {6}\) is \(4\).

Let’s call \(M(n)\) the largest value of \(a < n\) such that \(a^2 \equiv a \pmod {n}\).

So \(M(6) = 4\).

Find \(\sum M(n)\) for \(1 \leq n \leq 10^7\).

Project Euler Problem 407: Idempotents

Mathematical Analysis

Idempotent Equation

We need a^2 = a (mod n), i.e., a(a-1) = 0 (mod n). This means n | a(a-1).

Since gcd(a, a-1) = 1, by CRT, if n = p1^e1 * p2^e2 * … * pk^ek, then each prime power factor pi^ei must divide either a or a-1.

Chinese Remainder Theorem Approach

For each prime power p^e dividing n, we have two choices:

  • a = 0 (mod p^e), meaning p^e | a
  • a = 1 (mod p^e), meaning p^e | (a-1)

This gives 2^k solutions modulo n (where k is the number of distinct prime factors of n), all obtainable via CRT. We want the largest such solution less than n.

Computing M(n)

For each n:

  1. Factorize n into prime powers.
  2. For each subset of prime factors, construct a via CRT where a = 0 mod (product of selected prime powers) and a = 1 mod (product of remaining prime powers).
  3. Take the maximum such a with a < n.

Sieve Optimization

For efficiency, we use a sieve approach:

  • Precompute the smallest prime factor for all n up to 10^7.
  • For each n, factorize using the SPF sieve.
  • Enumerate all 2^k CRT solutions and find the maximum.

Editorial

a. Factorize n using SPF. b. Enumerate 2^k idempotents via CRT. We build a smallest-prime-factor sieve up to 10^7. We then iterate over each n from 1 to 10^7. Finally, sum all M(n).

Pseudocode

Build a smallest-prime-factor sieve up to 10^7
For each n from 1 to 10^7:
Sum all M(n)

Complexity Analysis

  • Sieve: O(N log log N)
  • Factorization: O(log n) per n
  • CRT enumeration: O(2^k) per n where k is the number of distinct prime factors. Since 2357111317*19 > 10^7, k <= 8.
  • Total: O(N * average 2^k) which is efficient in practice.

Answer

39782849136421\boxed{39782849136421}

Code

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

C++ project_euler/problem_407/solution.cpp
#include <bits/stdc++.h>
using namespace std;

/*
 * Project Euler Problem 407: Idempotents
 *
 * Find sum of M(n) for n = 1..10^7 where M(n) is the largest a < n
 * with a^2 = a (mod n).
 *
 * a(a-1) = 0 mod n. Since gcd(a,a-1) = 1, for each prime power p^e || n,
 * either p^e | a or p^e | (a-1). Enumerate via CRT.
 */

const int MAXN = 10000001;
int spf[MAXN]; // smallest prime factor

long long extgcd(long long a, long long b, long long &x, long long &y) {
    if (b == 0) { x = 1; y = 0; return a; }
    long long x1, y1;
    long long g = extgcd(b, a % b, x1, y1);
    x = y1;
    y = x1 - (a / b) * y1;
    return g;
}

// CRT: find x = r1 mod m1, x = r2 mod m2
// Returns (combined_r, combined_m)
pair<long long, long long> crt(long long r1, long long m1, long long r2, long long m2) {
    long long x, y;
    long long g = extgcd(m1, m2, x, y);
    long long lcm = m1 / g * m2;
    long long diff = r2 - r1;
    long long r = (r1 + m1 * ((diff / g % (m2 / g) * x) % (m2 / g))) % lcm;
    if (r < 0) r += lcm;
    return {r, lcm};
}

int main() {
    ios_base::sync_with_stdio(false);

    // Sieve smallest prime factor
    for (int i = 2; i < MAXN; i++) spf[i] = i;
    for (int i = 2; (long long)i * i < MAXN; i++) {
        if (spf[i] == i) { // i is prime
            for (int j = i * i; j < MAXN; j += i) {
                if (spf[j] == j) spf[j] = i;
            }
        }
    }

    long long total = 0;

    for (int n = 2; n < MAXN; n++) {
        // Factorize n
        vector<int> primes_powers; // prime power factors
        int tmp = n;
        while (tmp > 1) {
            int p = spf[tmp];
            int pe = 1;
            while (tmp % p == 0) {
                tmp /= p;
                pe *= p;
            }
            primes_powers.push_back(pe);
        }

        int k = primes_powers.size();
        long long best = 1;

        // Enumerate all 2^k combinations
        for (int mask = 0; mask < (1 << k); mask++) {
            // For each prime power: if bit is 0, a = 0 mod pe; if bit is 1, a = 1 mod pe
            long long r = 0, m = 1;
            for (int i = 0; i < k; i++) {
                long long ri = (mask >> i) & 1;
                long long mi = primes_powers[i];
                auto [nr, nm] = crt(r, m, ri, mi);
                r = nr;
                m = nm;
            }
            if (r > 0 && r < n) {
                best = max(best, r);
            }
        }

        total += best;
    }

    printf("%lld\n", total);
    return 0;
}