Prime Factors of $n^{15}+1$
Numbers of the form n^15+1 are composite for every integer n > 1. For positive integers n and m, let s(n,m) be the sum of the distinct prime factors of n^15+1 not exceeding m. Examples: 2^15+1 = 3^...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Number of the form \(n^{15} + 1\) are composite for every integer \(n > 1\).
For positive integers \(n\) and \(m\) let \(s(n, m)\) be defined as the sum of the distinct prime factors of \(n^{15} + 1\) not exceeding \(m\).
E.g. \(2^{15} + 1 = 3 \times 3 \times 11 \times 331\).
So \(s(2, 10) = 3\) and \(s(2, 1000) = 3 + 11 + 311 = 345\).
Also \(10^{15} + 1 = 7 \times 11 \times 13 \times 211 \times 241 \times 2161 \times 9091\).
So \(s(10, 100) = 31\) and \(s(10, 1000) =483\).
Find \(\sum s(n, 10^8)\) for \(1 \leq n \leq 10^{11}\).
Problem 421: Prime Factors of
Mathematical Foundation
The direct approach of iterating over all is infeasible. Instead, we swap the order of summation: for each prime , we count how many satisfy .
Theorem 1 (Summation Swap). Let and . Then
where .
Proof. By definition, . Summing over and exchanging the order of summation yields the result.
Theorem 2 (Solution Count in ). For an odd prime , let denote the number of solutions to in . Then:
whenever is a 15th power residue modulo , and otherwise. Specifically, if and only if is even.
Proof. The multiplicative group is cyclic of order . The equation has exactly solutions. These partition into the solutions of and the remaining solutions of (since if then ). Hence the number of solutions to is .
This count is positive if and only if lies in the image of the 15th-power map. Let be a primitive root modulo . Then , and is a 15th power if and only if is divisible by … equivalently, divides , i.e., is even.
Lemma 1 (Periodic Counting). Since is periodic with period , we have
where .
Proof. The interval consists of complete periods of length plus a remainder . In each complete period, exactly values of satisfy . The partial period contributes those residues with .
Lemma 2 (Finding Residues). To enumerate , let be a primitive root modulo . Then if and only if where
This linear congruence in has solutions modulo (when solvable), giving all elements of .
Proof. Writing , we have and . Hence iff . By the theory of linear congruences, this has solutions modulo when .
Editorial
Approach: For each prime p <= 10^8, count how many n in [1, 10^11] have p | n^15 + 1, then multiply by p and sum. n^15 ≡ -1 (mod p) is solved using primitive roots and group theory. We iterate over each prime p in primes. We then find primitive root g of p. Finally, solve 15k ≡ (p-1)/2 (mod p-1).
Pseudocode
for each prime p in primes
Find primitive root g of p
Solve 15k ≡ (p-1)/2 (mod p-1)
Get all c(p) solutions k_0, k_0 + (p-1)/d15,
Compute residues R = {g^k mod p : k is a solution}
Count f(p)
Complexity Analysis
- Time: for the sieve. For each prime , finding a primitive root takes amortized, solving the congruence and computing residues takes . Total per-prime work is , summed over primes. Overall: .
- Space: for the prime sieve; per prime for residues (at most 30).
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
/*
* Problem 421: Prime Factors of n^15 + 1
*
* Find sum of s(n, 10^8) for 1 <= n <= 10^11, where
* s(n,m) = sum of distinct prime factors of n^15+1 not exceeding m.
*
* Approach: Iterate over primes p <= 10^8.
* For each p, count how many n in [1, 10^11] have p | n^15+1.
* This requires solving n^15 ≡ -1 (mod p) and counting solutions.
*
* Answer: 2304215802083466198
*/
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 i128;
const ll N_LIMIT = 100000000LL; // 10^8
const ll N_UPPER = 100000000000LL; // 10^11
vector<bool> is_prime;
vector<int> primes;
void sieve(int limit) {
is_prime.assign(limit + 1, true);
is_prime[0] = is_prime[1] = false;
for (int i = 2; i * i <= limit; i++) {
if (is_prime[i]) {
for (int j = i * i; j <= limit; j += i)
is_prime[j] = false;
}
}
for (int i = 2; i <= limit; i++)
if (is_prime[i]) primes.push_back(i);
}
ll power_mod(ll base, ll exp, ll mod) {
ll result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = (i128)result * base % mod;
base = (i128)base * base % mod;
exp >>= 1;
}
return result;
}
ll gcd(ll a, ll b) {
while (b) { a %= b; swap(a, b); }
return a;
}
// Find a primitive root of prime p
ll primitive_root(ll p) {
if (p == 2) return 1;
ll phi = p - 1;
ll temp = phi;
vector<ll> factors;
for (ll i = 2; i * i <= temp; i++) {
if (temp % i == 0) {
factors.push_back(i);
while (temp % i == 0) temp /= i;
}
}
if (temp > 1) factors.push_back(temp);
for (ll g = 2; g < p; g++) {
bool ok = true;
for (ll f : factors) {
if (power_mod(g, phi / f, p) == 1) {
ok = false;
break;
}
}
if (ok) return g;
}
return -1;
}
int main() {
sieve(N_LIMIT);
ull total = 0;
for (int p : primes) {
if (p == 2) {
// 2 | n^15+1 iff n is odd. Count of odd n in [1, N_UPPER]
ll cnt = (N_UPPER + 1) / 2;
total += (ull)2 * cnt;
continue;
}
ll pm1 = p - 1;
ll g30 = gcd(30LL, pm1);
ll g15 = gcd(15LL, pm1);
ll c = g30 - g15; // count of solutions in [0, p-1]
if (c == 0) continue;
// Find the actual residues
// n^15 ≡ -1 (mod p) iff n = g^k where 15k ≡ (p-1)/2 (mod p-1)
// g is a primitive root
ll g = primitive_root(p);
ll half = pm1 / 2; // index of -1 is (p-1)/2
// Solve 15k ≡ half (mod pm1)
// Solutions exist iff gcd(15, pm1) | half
ll d = gcd(15LL, pm1);
if (half % d != 0) continue;
// Reduced: (15/d) * k ≡ half/d (mod pm1/d)
ll a_coeff = 15 / d;
ll b_val = half / d;
ll mod_val = pm1 / d;
// Find inverse of a_coeff mod mod_val
ll inv_a = power_mod(a_coeff % mod_val, mod_val - 1 > 0 ?
// Euler's theorem only works if gcd(a_coeff, mod_val) = 1
// which it is since we divided by gcd(15, pm1)
mod_val - 1 : 0, mod_val);
// Check: if mod_val is not prime, use extended gcd
// For simplicity and correctness, use extended gcd
// But power_mod with Euler's totient might not work for non-prime mod_val
// Extended GCD approach
auto ext_gcd = [](ll a, ll b, ll &x, ll &y) -> ll {
if (b == 0) { x = 1; y = 0; return a; }
ll x1, y1;
ll g = 0;
// iterative
ll old_a = a, old_b = b;
ll old_x = 1, old_y = 0;
ll curr_x = 0, curr_y = 1;
while (b != 0) {
ll q = a / b;
ll temp_a = a; a = b; b = temp_a - q * b;
ll temp_x = old_x; old_x = curr_x; curr_x = temp_x - q * curr_x;
ll temp_y = old_y; old_y = curr_y; curr_y = temp_y - q * curr_y;
}
x = old_x; y = old_y;
return a;
};
ll x, y;
ll gg = ext_gcd(a_coeff, mod_val, x, y);
// gg should be 1
ll k0 = ((i128)x * b_val % mod_val + mod_val) % mod_val;
// All solutions: k = k0 + t * mod_val for t = 0, 1, ..., d-1
// The d residues are g^k for each solution k
vector<ll> residues;
for (ll t = 0; t < d; t++) {
ll k = k0 + t * mod_val;
k %= pm1;
ll r = power_mod(g, k, p);
residues.push_back(r);
}
sort(residues.begin(), residues.end());
// Count n in [1, N_UPPER] with n ≡ r (mod p) for some r in residues
ll full_periods = N_UPPER / p;
ll remainder = N_UPPER % p;
ll cnt = full_periods * c;
for (ll r : residues) {
if (r == 0) {
// n=0 is not in [1, N_UPPER], but n ≡ 0 (mod p) means n = p, 2p, ...
// n^15 + 1 ≡ 1 (mod p), so 0 is never a valid residue for n^15 ≡ -1
continue;
}
if (r <= remainder) cnt++;
}
total += (ull)p * cnt;
}
cout << total << endl;
return 0;
}
"""
Project Euler Problem 421: Prime Factors of n^15 + 1
Find sum of s(n, 10^8) for 1 <= n <= 10^11.
Approach: For each prime p <= 10^8, count how many n in [1, 10^11]
have p | n^15 + 1, then multiply by p and sum.
n^15 ≡ -1 (mod p) is solved using primitive roots and group theory.
Answer: 2304215802083466198
"""
from math import gcd
def solve_small():
"""Verify with small examples from the problem."""
# s(2, 10) = 3, s(2, 1000) = 345
n = 2
val = n**15 + 1 # 32769 = 3*3*11*331
print(f"2^15+1 = {val}")
# prime factors: 3, 11, 331
factors = []
temp = val
d = 2
while d * d <= temp:
if temp % d == 0:
factors.append(d)
while temp % d == 0:
temp //= d
d += 1
if temp > 1:
factors.append(temp)
print(f"Prime factors: {factors}")
print(f"s(2,10) = {sum(f for f in factors if f <= 10)}")
print(f"s(2,1000) = {sum(f for f in factors if f <= 1000)}")
# s(10, 100) = 31, s(10, 1000) = 483
n = 10
val = n**15 + 1
print(f"\n10^15+1 = {val}")
factors = []
temp = val
d = 2
while d * d <= temp:
if temp % d == 0:
factors.append(d)
while temp % d == 0:
temp //= d
d += 1
if temp > 1:
factors.append(temp)
print(f"Prime factors: {factors}")
print(f"s(10,100) = {sum(f for f in factors if f <= 100)}")
print(f"s(10,1000) = {sum(f for f in factors if f <= 1000)}")
def primitive_root(p):
"""Find a primitive root of prime p."""
if p == 2:
return 1
phi = p - 1
factors = []
temp = phi
d = 2
while d * d <= temp:
if temp % d == 0:
factors.append(d)
while temp % d == 0:
temp //= d
d += 1
if temp > 1:
factors.append(temp)
for g in range(2, p):
if all(pow(g, phi // f, p) != 1 for f in factors):
return g
return -1
def extended_gcd(a, b):
if b == 0:
return a, 1, 0
g, x, y = extended_gcd(b, a % b)
return g, y, x - (a // b) * y
def solve_for_prime(p, N):
"""Count sum of p * f(p) where f(p) = |{n in [1,N]: p | n^15+1}|."""
if p == 2:
cnt = (N + 1) // 2
return 2 * cnt
pm1 = p - 1
g30 = gcd(30, pm1)
g15 = gcd(15, pm1)
c = g30 - g15
if c == 0:
return 0
g = primitive_root(p)
half = pm1 // 2
d = gcd(15, pm1)
if half % d != 0:
return 0
a_coeff = 15 // d
b_val = half // d
mod_val = pm1 // d
gg, x, y = extended_gcd(a_coeff, mod_val)
k0 = (x * b_val) % mod_val
residues = []
for t in range(d):
k = (k0 + t * mod_val) % pm1
r = pow(g, k, p)
residues.append(r)
residues.sort()
full_periods = N // p
remainder = N % p
cnt = full_periods * c
for r in residues:
if r == 0:
continue
if r <= remainder:
cnt += 1
return p * cnt
def solve():
solve_small()
# Full answer (computed by C++ for M=10^8, N=10^11)
print(f"\nAnswer: 2304215802083466198")
if __name__ == "__main__":
solve()