All Euler problems
Project Euler

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).

Source sync May 21, 2026
Problem #0934
Level Level 25
Solved By 427
Languages C++, Python
Answer 292137809490441370
Length 317 words
number_theorymodular_arithmeticbrute_force

Problem Statement

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

We define the unlucky prime of a number \(n\), denoted \(u(n)\), as the smallest prime number \(p\) such that the remainder of \(n\) divided by \(p\) (i.e. \(n \bmod p\)) is not a multiple of seven.

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 gg with gcd⁡(g,p)=1\gcd(g, p) = 1 is a primitive root modulo a prime pp if ord⁡p(g)=p−1\operatorname{ord}_p(g) = p - 1, i.e., gg generates the cyclic group (Z/pZ)∗(\mathbb{Z}/p\mathbb{Z})^*.

Theorem 1 (Existence of primitive roots). Every prime pp possesses exactly φ(p−1)\varphi(p - 1) primitive roots modulo pp.

Proof. The group (Z/pZ)∗(\mathbb{Z}/p\mathbb{Z})^* is cyclic of order p−1p - 1 (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 nn has exactly φ(n)\varphi(n) generators. □\square

Theorem 2 (Primitive root test). Let pp be prime and let q1,…,qsq_1, \ldots, q_s be the distinct prime factors of p−1p - 1. Then gg is a primitive root modulo pp if and only if

g(p−1)/qi≢1(modp)for all i=1,…,s.g^{(p-1)/q_i} \not\equiv 1 \pmod{p} \quad \text{for all } i = 1, \ldots, s.

Proof. (⇒\Rightarrow) If gg is a primitive root, then ord⁡p(g)=p−1\operatorname{ord}_p(g) = p - 1. Since (p−1)/qi<p−1(p-1)/q_i < p - 1, we have g(p−1)/qi≢1g^{(p-1)/q_i} \not\equiv 1.

(⇐\Leftarrow) Suppose ord⁡p(g)=d<p−1\operatorname{ord}_p(g) = d < p - 1. Then d∣(p−1)d \mid (p - 1) and d<p−1d < p - 1, so there exists a prime qi∣(p−1)q_i \mid (p - 1) such that d∣(p−1)/qid \mid (p-1)/q_i (since p−1p - 1 has a prime factor not dividing dd, or equivalently, (p−1)/d>1(p-1)/d > 1 implies some qi∣(p−1)/dq_i \mid (p-1)/d). This gives g(p−1)/qi≡(gd)(p−1)/(dqi)≡1g^{(p-1)/q_i} \equiv (g^d)^{(p-1)/(dq_i)} \equiv 1, a contradiction. □\square

Lemma 1 (Smallness of g(p)g(p)). Under the Generalized Riemann Hypothesis, g(p)=O((log⁡p)6)g(p) = O((\log p)^6). Unconditionally (Vinogradov), g(p)≤p0.499g(p) \leq p^{0.499} for sufficiently large pp. Empirically, g(p)≤6g(p) \leq 6 for the majority of primes, and g(p)=2g(p) = 2 for approximately 37% of primes below 10710^7.

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. □\square

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: O(Nlog⁡log⁡N)O(N \log \log N).
    • For each prime pp: factoring p−1p - 1 takes O(log⁡p)O(\log p) using the precomputed SPF table. Testing each candidate gg requires O(slog⁡p)O(s \log p) modular exponentiations, where s=ω(p−1)s = \omega(p-1) is the number of distinct prime factors of p−1p-1. By Lemma 1, g(p)g(p) is typically very small (constant on average), so the expected total work is O(π(N)⋅s‾⋅log⁡N)O(\pi(N) \cdot \overline{s} \cdot \log N) where s‾\overline{s} is the average value of ω(p−1)\omega(p-1), which is O(log⁡log⁡N)O(\log \log N).
    • Overall: O(Nlog⁡log⁡N)O(N \log \log N).
  • Space: O(N)O(N) for the sieve.

Answer

292137809490441370\boxed{292137809490441370}

Code

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

C++ project_euler/problem_934/solution.cpp
#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;
}