All Euler problems
Project Euler

Factorial Digit Sum

Let S(m) denote the sum of the decimal digits of a positive integer m. Compute S(100!).

Source sync Apr 19, 2026
Problem #0020
Level Level 00
Solved By 214,580
Languages C++, Python
Answer 648
Length 351 words
modular_arithmeticanalytic_mathnumber_theory

Problem Statement

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

\(n!\) means \(n \times (n - 1) \times \cdots \times 3 \times 2 \times 1\).

For example, \(10! = 10 \times 9 \times \cdots \times 3 \times 2 \times 1 = 3628800\),

and the sum of the digits in the number \(10!\) is \(3 + 6 + 2 + 8 + 8 + 0 + 0 = 27\).

Find the sum of the digits in the number \(100!\).

Problem 20: Factorial Digit Sum

Mathematical Development

Definition 1 (Digit sum). For a positive integer m=k=0d1ak10km = \sum_{k=0}^{d-1} a_k \cdot 10^k with digits ak{0,,9}a_k \in \{0, \ldots, 9\} and ad10a_{d-1} \ne 0, define S(m)=k=0d1akS(m) = \sum_{k=0}^{d-1} a_k.

Theorem 1 (Digit count of n!n!). The number of digits of n!n! is

d(n!)=log10(n!)+1,where log10(n!)=k=1nlog10(k).d(n!) = \lfloor \log_{10}(n!) \rfloor + 1, \quad \text{where } \log_{10}(n!) = \sum_{k=1}^{n} \log_{10}(k).

Proof. A positive integer mm has log10m+1\lfloor \log_{10} m \rfloor + 1 digits. Applying the multiplicative property of logarithms: log10(n!)=log10 ⁣(k=1nk)=k=1nlog10(k)\log_{10}(n!) = \log_{10}\!\bigl(\prod_{k=1}^{n} k\bigr) = \sum_{k=1}^{n} \log_{10}(k). \square

Corollary 1. By Stirling’s approximation, log10(n!)nlog10(n/e)+12log10(2πn)\log_{10}(n!) \approx n \log_{10}(n/e) + \frac{1}{2}\log_{10}(2\pi n). For n=100n = 100: log10(100!)157.97\log_{10}(100!) \approx 157.97, so d(100!)=158d(100!) = 158.

Theorem 2 (Digit sum congruence). For every positive integer mm, S(m)m(mod9)S(m) \equiv m \pmod{9}.

Proof. Since 101(mod9)10 \equiv 1 \pmod{9}, we have 10k1(mod9)10^k \equiv 1 \pmod{9} for all k0k \ge 0, hence m=ak10kak=S(m)(mod9)m = \sum a_k \cdot 10^k \equiv \sum a_k = S(m) \pmod{9}. \square

Theorem 3 (Legendre’s formula). For a prime pp and positive integer nn, the pp-adic valuation of n!n! is

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

Proof. Each factor k{1,,n}k \in \{1, \ldots, n\} contributes νp(k)\nu_p(k) to νp(n!)\nu_p(n!). The number of multiples of pip^i in {1,,n}\{1, \ldots, n\} is n/pi\lfloor n/p^i \rfloor. By inclusion, νp(n!)=k=1nνp(k)=i=1n/pi\nu_p(n!) = \sum_{k=1}^{n} \nu_p(k) = \sum_{i=1}^{\infty} \lfloor n/p^i \rfloor. (The sum is finite since n/pi=0\lfloor n/p^i \rfloor = 0 for pi>np^i > n.) \square

Proposition 1 (100!0(mod9)100! \equiv 0 \pmod{9}). We have ν3(100!)=100/3+100/9+100/27+100/81=33+11+3+1=48\nu_3(100!) = \lfloor 100/3 \rfloor + \lfloor 100/9 \rfloor + \lfloor 100/27 \rfloor + \lfloor 100/81 \rfloor = 33 + 11 + 3 + 1 = 48.

Proof. Direct application of Theorem 3 with p=3p = 3. Since ν3(100!)=482\nu_3(100!) = 48 \ge 2, we have 9100!9 \mid 100!, and by Theorem 2, S(100!)0(mod9)S(100!) \equiv 0 \pmod{9}. \square

Verification. S(100!)=648=72×9S(100!) = 648 = 72 \times 9, confirming 6480(mod9)648 \equiv 0 \pmod{9}.

Theorem 4 (Trailing zeros of n!n!). The number of trailing zeros of n!n! is ν5(n!)=i=1n/5i\nu_5(n!) = \sum_{i=1}^{\infty} \lfloor n/5^i \rfloor.

Proof. A trailing zero corresponds to a factor of 10=2×510 = 2 \times 5. Since ν2(n!)ν5(n!)\nu_2(n!) \ge \nu_5(n!) for all n1n \ge 1 (as multiples of 2 are more frequent than multiples of 5), the count of trailing zeros equals min ⁣(ν2(n!),ν5(n!))=ν5(n!)\min\!\bigl(\nu_2(n!), \nu_5(n!)\bigr) = \nu_5(n!). \square

Corollary 2. ν5(100!)=100/5+100/25=20+4=24\nu_5(100!) = \lfloor 100/5 \rfloor + \lfloor 100/25 \rfloor = 20 + 4 = 24. Hence 100!100! has 24 trailing zeros, which contribute nothing to S(100!)S(100!).

Proposition 2 (Bounds on S(100!)S(100!)). Since 100!100! has 158 digits:

1S(100!)9×158=1422.1 \le S(100!) \le 9 \times 158 = 1422.

The 134 non-trailing-zero digits have an average value near 4.54.5, giving a heuristic estimate 603\approx 603. The actual value 648648 is modestly above this estimate.

Proof. Lower bound: at least one digit is nonzero. Upper bound: each digit 9\le 9. \square

Editorial

We form n!n! by multiplying the integers from 2 through nn, then extract its decimal digits and add them. The second phase repeatedly takes the last digit with a modulo-10 operation and removes it with integer division until no digits remain. This is sufficient because every digit of n!n! is processed exactly once.

Pseudocode

Algorithm: Digit Sum of a Factorial
Require: An integer n ≥ 1.
Ensure: The sum of the decimal digits of n!.
1: Initialize F ← 1.
2: For each k in {2, 3, ..., n}, update F ← F · k.
3: Compute the decimal digit expansion of F.
4: Return the sum of those digits.

Complexity Analysis

Proposition 3 (Time complexity). The algorithm runs in O(n2logn)O(n^2 \log n) time.

Proof. Let d=d(n!)=Θ(nlogn)d = d(n!) = \Theta(n \log n) by Stirling’s approximation. At step kk, the running product has Θ(klogk)\Theta(k \log k) digits, and multiplying it by kk (a number with O(logn)O(\log n) digits) costs O(klogk)O(k \log k) using schoolbook multiplication. The total time is:

k=2nO(klogk)=O ⁣(lognk=2nk)=O(n2logn).\sum_{k=2}^{n} O(k \log k) = O\!\left(\log n \sum_{k=2}^{n} k\right) = O(n^2 \log n).

The final digit-extraction loop runs in O(d)=O(nlogn)O(d) = O(n \log n), which is dominated by the multiplication phase. \square

Proposition 4 (Space complexity). The algorithm uses Θ(nlogn)\Theta(n \log n) space.

Proof. The intermediate product requires O(d)=O(nlogn)O(d) = O(n \log n) digits of storage. \square

Answer

648\boxed{648}

Code

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

C++ project_euler/problem_020/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> digits = {1};

    for (int n = 2; n <= 100; n++) {
        int carry = 0;
        for (int j = 0; j < (int)digits.size(); j++) {
            int val = digits[j] * n + carry;
            digits[j] = val % 10;
            carry = val / 10;
        }
        while (carry > 0) {
            digits.push_back(carry % 10);
            carry /= 10;
        }
    }

    int sum = 0;
    for (int d : digits) sum += d;
    cout << sum << endl;
    return 0;
}