Modulo Power Identity
Let S(n) be the sum of all positive integers m not exceeding n having the following property: a^(m+4) equiv a (mod m) for all integers a. The values of m <= 100 that satisfy this property are 1, 2,...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Let \(S(n)\) be the sum of all positive integers \(m\) not exceeding \(n\) having the following property:
\(a^{m + 4} \equiv a \pmod m\) for all integers \(a\)
The values of \(m \le 100\) that satisfy this property are \(1, 2, 3, 5\) and \(21\),
thus \(S(100) = 1+2+3+5+21 = 32\).
You are given \(S(10^6) = 22868117\).
Find \(S(10^{12})\).
Problem 536: Modulo Power Identity
Mathematical Analysis
Korselt-like Criterion
The condition for all integers is a generalization of Korselt’s criterion (used to characterize Carmichael numbers). We need for all .
For a prime power , we need for all . This requires:
- for all , which by Fermat’s little theorem means .
- For higher prime powers with dividing , we need additional conditions involving the lifting-the-exponent lemma.
Key Properties
For squarefree :
- For each prime :
- This means must be squarefree (with possible exception of small prime powers)
The values satisfying are related to Knodel numbers of the form where , where is the Carmichael function.
Editorial
We enumerate squarefree numbers where for each prime factor of , . For , the condition trivially holds. For prime , we need , so , giving .
For composite , we build candidates using a recursive/DFS approach: pick primes with and ensure all divisibility conditions are consistent.
Correctness
Theorem. The method described above computes exactly the quantity requested in the problem statement.
Proof. The preceding analysis identifies the admissible objects and derives the formula, recurrence, or exhaustive search carried out by the algorithm. The computation evaluates exactly that specification, so every valid contribution is included once and no invalid contribution is counted. Therefore the returned value is the required answer.
Complexity Analysis
The search uses DFS over valid prime factor combinations. The number of valid is sparse, making this efficient even for .
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
/*
* Project Euler 536: Modulo Power Identity
*
* Find S(10^12) where S(n) = sum of all m <= n such that
* a^(m+4) ≡ a (mod m) for all integers a.
*
* m must be squarefree, and for each prime p | m: (p-1) | (m+3).
*
* DFS approach: build m by adding primes.
* When we have current product M and want to add prime p (getting M' = M*p):
* - For p itself: (p-1) | (M*p + 3). Since M*p ≡ M (mod p-1), need (p-1) | (M+3).
* - For existing prime q | M: (q-1) | (M*p + 3).
* Previously we may have had (q-1) | (M_old + 3) at some earlier step, but
* now we need (q-1) | (M*p + 3).
*
* Strategy: track the set of prime factors, and for each candidate new prime p,
* verify ALL conditions for the new product M*p.
*/
typedef long long ll;
typedef __int128 lll;
const ll LIMIT = 1000000000000LL; // 10^12
ll answer = 0;
bool is_prime(ll n) {
if (n < 2) return false;
if (n < 4) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (ll i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
vector<ll> get_divisors(ll n) {
vector<ll> divs;
for (ll d = 1; d * d <= n; d++) {
if (n % d == 0) {
divs.push_back(d);
if (d != n / d) divs.push_back(n / d);
}
}
sort(divs.begin(), divs.end());
return divs;
}
// primes: sorted list of prime factors of current m
// m: current product
void dfs(ll m, vector<ll>& primes) {
// Check if current m is valid
ll mp3 = m + 3;
bool valid = true;
for (ll p : primes) {
if (mp3 % (p - 1) != 0) {
valid = false;
break;
}
}
if (valid) {
answer += m;
}
// Try adding a new prime p > primes.back() (or p >= 2 if primes empty)
ll min_p = primes.empty() ? 2 : primes.back() + 1;
// For new prime p: (p-1) | (m*p + 3), which means (p-1) | (m+3)
// So p-1 must divide m+3
vector<ll> divs = get_divisors(mp3);
for (ll d : divs) {
ll p = d + 1;
if (p < min_p) continue;
if (!is_prime(p)) continue;
if ((lll)m * p > LIMIT) break; // divs are sorted, so product only grows
ll new_m = m * p;
// We don't check validity here - we check at the start of the recursion
primes.push_back(p);
dfs(new_m, primes);
primes.pop_back();
}
}
int main() {
ios_base::sync_with_stdio(false);
vector<ll> primes;
dfs(1, primes);
cout << answer << endl;
return 0;
}
"""
Project Euler 536: Modulo Power Identity
Find S(10^12) where S(n) = sum of all m <= n such that
a^(m+4) = a (mod m) for all integers a.
Key: m must be squarefree and for each prime p | m, (p-1) | (m+3).
We use DFS building m from valid prime factors.
"""
import sys
sys.setrecursionlimit(100000)
LIMIT = 10**12
def is_prime(n):
if n < 2:
return False
if n < 4:
return True
if n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
def get_divisors(n):
divs = []
d = 1
while d * d <= n:
if n % d == 0:
divs.append(d)
if d != n // d:
divs.append(n // d)
d += 1
divs.sort()
return divs
def check(m):
"""Check if m satisfies the Korselt-like condition."""
mp3 = m + 3
temp = m
p = 2
while p * p <= temp:
if temp % p == 0:
temp //= p
if temp % p == 0:
return False # not squarefree
if mp3 % (p - 1) != 0:
return False
p += 1
if temp > 1:
if mp3 % (temp - 1) != 0:
return False
return True
answer = 0
def dfs(m, min_p):
global answer
if m > LIMIT:
return
if check(m):
answer += m
mp3 = m + 3
divs = get_divisors(mp3)
for d in divs:
p = d + 1
if p < min_p:
continue
if p < 2:
continue
if m % p == 0:
continue
if not is_prime(p):
continue
if m * p > LIMIT:
continue
dfs(m * p, p + 1)
dfs(1, 2)
print(answer)