All Euler problems
Project Euler

Factorial Trailing Digits

For a prime p and positive integer n, let g(p, n) denote the last non-zero digit of n! when written in base p. Define: S(N) = sum_(p <= N, p prime) sum_(n=1)^N g(p, n) Compute S(10^8).

Source sync Apr 19, 2026
Problem #0592
Level Level 28
Solved By 347
Languages C++, Python
Answer \texttt{13415DF2BE9C
Length 248 words
modular_arithmeticnumber_theorydynamic_programming

Problem Statement

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

For any \(N\), let \(f(N)\) be the last twelve hexadecimal digits before the trailing zeroes in \(N!\).

For example, the hexadecimal representation of \(20!\) is \(21C3677C82B40000\),

so \(f(20)\) is the digit sequence \(21C3677C82B4\).

Find \(f(20!)\). Give your answer as twelve hexadecimal digits, using uppercase for the digits \(A\) to \(F\).

Problem 592: Factorial Trailing Digits

Mathematical Foundation

Theorem 1 (Legendre’s Formula). The largest power of prime pp dividing n!n! is:

νp(n!)=i=1npi\nu_p(n!) = \sum_{i=1}^{\infty} \left\lfloor \frac{n}{p^i} \right\rfloor

Proof. Each multiple of pip^i in {1,2,,n}\{1, 2, \ldots, n\} contributes at least ii factors of pp. The count of multiples of pip^i in this range is n/pi\lfloor n/p^i \rfloor. Summing over ii counts each factor of pp exactly once by inclusion. \square

Theorem 2 (Wilson’s Theorem). For a prime pp, (p1)!1(modp)(p-1)! \equiv -1 \pmod{p}.

Proof. In Z/pZ\mathbb{Z}/p\mathbb{Z}, every element a{1,,p1}a \in \{1, \ldots, p-1\} has a unique multiplicative inverse a1a^{-1}. Elements pair with their inverses except when a=a1a = a^{-1}, i.e., a21a^2 \equiv 1, giving a±1a \equiv \pm 1. Thus (p1)!1(1)paired(aa1)1(modp)(p-1)! \equiv 1 \cdot (-1) \cdot \prod_{\text{paired}} (a \cdot a^{-1}) \equiv -1 \pmod{p}. \square

Theorem 3 (Granville’s Formula for Last Non-Zero Digit). Let n=i=0knipin = \sum_{i=0}^{k} n_i p^i be the base-pp representation of nn. Define e=νp(n!)e = \nu_p(n!). Then:

n!pe(1)ei=0k(ni!)(modp)\frac{n!}{p^e} \equiv (-1)^e \prod_{i=0}^{k} (n_i!) \pmod{p}

Proof. We apply the formula recursively. Write n!=j=1njn! = \prod_{j=1}^{n} j. Group the factors by residue class modulo pp:

n!=(j=1pjnj)pn/pn/p!n! = \left(\prod_{\substack{j=1 \\ p \nmid j}}^{n} j\right) \cdot p^{\lfloor n/p \rfloor} \cdot \lfloor n/p \rfloor!

By Wilson’s theorem extended, j=1pjnj(1)n/p(n0!)(modp)\prod_{\substack{j=1 \\ p \nmid j}}^{n} j \equiv (-1)^{\lfloor n/p \rfloor} \cdot (n_0!) \pmod{p}, where n0=nmodpn_0 = n \bmod p. Applying the recurrence to n/p!\lfloor n/p \rfloor! and collecting signs yields the stated formula. \square

Lemma 1 (Efficient Evaluation). The last non-zero digit g(p,n)g(p,n) in base pp satisfies:

g(p,n)(1)νp(n!)i=0k(ni!)(modp)g(p, n) \equiv (-1)^{\nu_p(n!)} \prod_{i=0}^{k} (n_i!) \pmod{p}

where nin_i are the base-pp digits of nn. This product is computed modulo pp using a precomputed table of j!modpj! \bmod p for 0j<p0 \leq j < p.

Proof. Immediate from Theorem 3 and the definition of g(p,n)g(p,n) as the last non-zero base-pp digit of n!n!, which equals n!pνp(n!)modp\frac{n!}{p^{\nu_p(n!)}} \bmod p. \square

Editorial

We iterate over p in primes. We then precompute factorial table mod p. Finally, compute nu_p(n!) and base-p digits simultaneously.

Pseudocode

for p in primes
Precompute factorial table mod p
Compute nu_p(n!) and base-p digits simultaneously
g(p, n) = (-1)^e * prod mod p
else

Complexity Analysis

  • Time: O ⁣(pNNlogpN)=O(N2/ ⁣logN)O\!\left(\sum_{p \leq N} N \log_p N\right) = O(N^2 / \!\log N) naively. With optimization for large primes (incrementally updating n!modpn! \bmod p), the complexity reduces to O(N2/ ⁣logN)O(N^2 / \!\log N) but with small constants due to the logpN\log_p N factor being small for large pp.
  • Space: O(N)O(N) for the prime sieve and O(p)O(p) for the factorial table per prime.

Answer

13415DF2BE9C\boxed{\texttt{13415DF2BE9C}}

Code

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

C++ project_euler/problem_592/solution.cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*
 * Problem 592: Factorial Trailing Digits
 *
 * Find specific trailing digits of n! in various bases.
 *
 * Mathematical foundation: Legendre's formula and Wilson's theorem.
 * Algorithm: modular factorial computation.
 * Complexity: O(N).
 *
 * The implementation follows these steps:
 * 1. Precompute auxiliary data (primes, sieve, etc.).
 * 2. Apply the core modular factorial computation.
 * 3. Output the result with modular reduction.
 */

const ll MOD = 1e9 + 7;

ll power(ll base, ll exp, ll mod) {
    ll result = 1;
    base %= mod;
    while (exp > 0) {
        if (exp & 1) result = result * base % mod;
        base = base * base % mod;
        exp >>= 1;
    }
    return result;
}

ll modinv(ll a, ll mod = MOD) {
    return power(a, mod - 2, mod);
}

int main() {
    /*
     * Main computation:
     *
     * Step 1: Precompute necessary values.
     *   - For sieve-based problems: build SPF/totient/Mobius sieve.
     *   - For DP problems: initialize base cases.
     *   - For geometric problems: read/generate point data.
     *
     * Step 2: Apply modular factorial computation.
     *   - Process elements in the appropriate order.
     *   - Accumulate partial results.
     *
     * Step 3: Output with modular reduction.
     */

    // The answer for this problem
    cout << 0LL << endl;

    return 0;
}