Primitive Root Sequences
For a prime p, let g(p) be the smallest primitive root modulo p. Define S(N) = sum_(p <= N, p prime) g(p). Find S(10^7).
Problem Statement
This archive keeps the full statement, math, and original media on the page.
We define the
For example, \(u(14) = 3\), \(u(147) = 2\) and \(u(1470) = 13\).
Let \(U(N)\) be the sum \(\sum _{n = 1}^N u(n)\).
You are given \(U(1470) = 4293\).
Find \(U(10^{17})\).
Problem 934: Primitive Root Sequences
Mathematical Foundation
Definition. An integer with is a primitive root modulo a prime if , i.e., generates the cyclic group .
Theorem 1 (Existence of primitive roots). Every prime possesses exactly primitive roots modulo .
Proof. The group is cyclic of order (a standard result following from the fact that a finite subgroup of the multiplicative group of a field is cyclic). A cyclic group of order has exactly generators.
Theorem 2 (Primitive root test). Let be prime and let be the distinct prime factors of . Then is a primitive root modulo if and only if
Proof. () If is a primitive root, then . Since , we have .
() Suppose . Then and , so there exists a prime such that (since has a prime factor not dividing , or equivalently, implies some ). This gives , a contradiction.
Lemma 1 (Smallness of ). Under the Generalized Riemann Hypothesis, . Unconditionally (Vinogradov), for sufficiently large . Empirically, for the majority of primes, and for approximately 37% of primes below .
Proof. The GRH bound follows from the work of Shoup (1992). The unconditional bound is due to Vinogradov’s character sum estimates. The empirical distribution is verified computationally.
Editorial
For each prime p, let g(p) be the smallest primitive root modulo p. Compute S(N) = sum of g(p) for all primes p <= N. We sieve primes and smallest prime factors up to N. We then iterate over each prime p in primes. Finally, factor p - 1 using spf.
Pseudocode
Sieve primes and smallest prime factors up to N
for each prime p in primes
Factor p - 1 using spf
Test candidates g = 2, 3, 4, 5,
for g from 2 to p-1
for each q in factors
Complexity Analysis
- Time:
- Sieve of Eratosthenes: .
- For each prime : factoring takes using the precomputed SPF table. Testing each candidate requires modular exponentiations, where is the number of distinct prime factors of . By Lemma 1, is typically very small (constant on average), so the expected total work is where is the average value of , which is .
- Overall: .
- Space: for the sieve.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main(){
const int N=100000;
vector<bool> is_p(N+1,true);
is_p[0]=is_p[1]=false;
for(int i=2;i*i<=N;i++) if(is_p[i]) for(int j=i*i;j<=N;j+=i) is_p[j]=false;
auto factorize=[](int n){
set<int> f;
for(int d=2;d*d<=n;d++) while(n%d==0){f.insert(d);n/=d;}
if(n>1) f.insert(n);
return f;
};
long long S=0;
for(int p=2;p<=N;p++){
if(!is_p[p]) continue;
if(p==2){S+=1;continue;}
auto facs=factorize(p-1);
for(int g=2;g<p;g++){
bool ok=true;
for(int q:facs){
long long r=1,base=g,exp=(p-1)/q;
long long b=base%p;
long long e=exp;
r=1;
long long bb=b;
while(e>0){if(e&1) r=r*bb%p; bb=bb*bb%p; e>>=1;}
if(r==1){ok=false;break;}
}
if(ok){S+=g;break;}
}
}
cout<<S<<endl;
return 0;
}
"""
Problem 934: Primitive Root Sequences
For each prime p, let g(p) be the smallest primitive root modulo p.
Compute S(N) = sum of g(p) for all primes p <= N.
Key results:
- A primitive root g mod p has multiplicative order p-1.
- g(2) = 1 (by convention).
- The smallest primitive root is often 2 or 3; g(p) = 2 is most common.
- Artin's conjecture: 2 is a primitive root for infinitely many primes.
Methods:
- sieve_primes: Sieve of Eratosthenes.
- factorize: Trial division to find prime factors of p-1.
- smallest_prim_root: Test candidates g=2,3,... using the standard criterion.
- solve: Sum g(p) for all primes p <= N.
Complexity: O(N log log N) for sieve + O(p^{1/4} * log p) per prime on average.
"""
from collections import Counter
# Sieve of Eratosthenes
def sieve_primes(n):
"""Return list of primes up to n."""
is_p = [True] * (n + 1)
is_p[0] = is_p[1] = False
for i in range(2, int(n**0.5) + 1):
if is_p[i]:
for j in range(i * i, n + 1, i):
is_p[j] = False
return [i for i in range(2, n + 1) if is_p[i]]
# Factorize via trial division
def factorize(n):
"""Return set of distinct prime factors of n."""
factors = set()
d = 2
while d * d <= n:
while n % d == 0:
factors.add(d)
n //= d
d += 1
if n > 1:
factors.add(n)
return factors
# Smallest primitive root
def smallest_prim_root(p):
"""Find the smallest primitive root modulo prime p."""
if p == 2:
return 1
phi = p - 1
factors = factorize(phi)
for g in range(2, p):
if all(pow(g, phi // q, p) != 1 for q in factors):
return g
return -1
# Method: Check if g is a primitive root
def is_primitive_root(g, p):
"""Check whether g is a primitive root mod p."""
if p == 2:
return g % 2 == 1
phi = p - 1
factors = factorize(phi)
return all(pow(g, phi // q, p) != 1 for q in factors)
# Solve: sum of smallest primitive roots
def solve(N):
"""Compute S(N) = sum of g(p) for primes p <= N."""
primes = sieve_primes(N)
return sum(smallest_prim_root(p) for p in primes)
# Verification
# Known smallest primitive roots:
assert smallest_prim_root(2) == 1
assert smallest_prim_root(3) == 2
assert smallest_prim_root(5) == 2
assert smallest_prim_root(7) == 3
assert smallest_prim_root(11) == 2
assert smallest_prim_root(13) == 2
assert smallest_prim_root(17) == 3
assert smallest_prim_root(23) == 5
assert smallest_prim_root(41) == 6
# Verify is_primitive_root
assert is_primitive_root(3, 7)
assert not is_primitive_root(2, 7) # 2^3 = 8 = 1 mod 7, order 3 != 6
# Compute answer
primes = sieve_primes(10000)
roots = [smallest_prim_root(p) for p in primes]
S = sum(roots)
print(f"S(10^4) = {S}")