Project Euler Problem 160
For any N, let f(N) be the last five digits before the trailing zeroes in N!.
Solution
Answer: 16576
We seek the last five nonzero digits of
$$N! \quad \text{with } N=10^{12}.$$
Define $f(N)$ as the last five digits before trailing zeroes of $N!$.
The problem is therefore:
$$f(10^{12}).$$
1. Mathematical analysis
Trailing zeroes come from factors of $10=2\cdot5$.
Since factorials contain many more 2s than 5s, the number of trailing zeroes is exactly the exponent of 5 in $N!$:
$$v_5(N!)=\sum_{k\ge1}\left\lfloor \frac{N}{5^k}\right\rfloor.$$
If we remove all factors of $10$, what remains is
$$\frac{N!}{10^{v_5(N!)}} = \frac{N!}{2^{v_5(N!)}5^{v_5(N!)}} = 2^{v_2(N!)-v_5(N!)} \cdot \prod_{m\le N,;5\nmid m} m.$$
We only need this modulo $10^5=100000$.
Because powers of 2 are not invertible modulo $10^5$, it is standard to work modulo
$$2^5=32 \qquad\text{and}\qquad 5^5=3125,$$
then combine via CRT.
Step 1: Remove all 2s and 5s from each term
Define
$$g(n)=\prod_{k=1}^n \frac{k}{2^{v_2(k)}5^{v_5(k)}},$$
i.e. the product of the “reduced” parts after stripping all 2s and 5s.
Then
$$f(n)\equiv g(n)\cdot 2^{v_2(n!)-v_5(n!)} \pmod{100000}.$$
So the problem becomes computing:
- the excess power of 2,
- the reduced product $g(n)$.
2. Structure modulo $10^5$
The key observation is periodicity.
Consider numbers coprime to 10 modulo $10^5$.
They form a multiplicative group of size
$$\varphi(100000)=40000.$$
The reduced product behaves recursively because removing factors of 2 and 5 naturally groups numbers by blocks of 5.
A classical derivation yields:
$$g(n) = g!\left(\left\lfloor\frac n5\right\rfloor\right) \cdot G(n\bmod 100000) \cdot (-1)^{\lfloor n/100000\rfloor} \pmod{100000},$$
where $G(m)$ is the cumulative product of reduced residues up to $m$.
The recursion depth is only about
$$\log_5(10^{12}) \approx 18.$$
Thus the whole computation is very fast.
3. Efficient computation
We precompute for $0\le k<100000$:
$$R(k)=\text{reduced part of }k$$
(removing all factors of 2 and 5),
and prefix products
$$P(m)=\prod_{k=1}^m R(k)\pmod{100000}.$$
Then recursively compute:
$$g(n)= g!\left(\left\lfloor n/5\right\rfloor\right) \cdot P(n\bmod 100000) \cdot P(99999)^{\lfloor n/100000\rfloor} \pmod{100000}.$$
Finally multiply by the leftover power of 2:
$$2^{v_2(n!)-v_5(n!)}.$$
4. Python implementation
MOD = 100000
# ---------------------------------------------------------
# Compute exponent of prime p in n!
# ---------------------------------------------------------
def vp_factorial(n, p):
s = 0
while n:
n //= p
s += n
return s
# ---------------------------------------------------------
# Remove all factors of 2 and 5 from x
# ---------------------------------------------------------
def reduce_25(x):
while x % 2 == 0:
x //= 2
while x % 5 == 0:
x //= 5
return x % MOD
# ---------------------------------------------------------
# Precompute prefix products of reduced numbers
# ---------------------------------------------------------
prefix = [1] * MOD
for i in range(1, MOD):
prefix[i] = (prefix[i - 1] * reduce_25(i)) % MOD
block_product = prefix[-1]
# ---------------------------------------------------------
# Recursive computation of reduced factorial product
# ---------------------------------------------------------
def g(n):
if n == 0:
return 1
q, r = divmod(n, MOD)
# contribution from full blocks
ans = pow(block_product, q, MOD)
# contribution from partial block
ans = (ans * prefix[r]) % MOD
# recurse on division by 5
ans = (ans * g(n // 5)) % MOD
return ans
# ---------------------------------------------------------
# Main computation
# ---------------------------------------------------------
N = 10**12
# excess powers of 2 after cancelling 5s
e2 = vp_factorial(N, 2)
e5 = vp_factorial(N, 5)
extra_twos = e2 - e5
# reduced product
ans = g(N)
# restore leftover powers of 2
ans = (ans * pow(2, extra_twos, MOD)) % MOD
print(ans)
5. Code walkthrough
vp_factorial
def vp_factorial(n, p):
Computes the exponent of prime $p$ in $n!$:
$$v_p(n!)=\sum_{k\ge1}\left\lfloor \frac{n}{p^k}\right\rfloor.$$
reduce_25
def reduce_25(x):
Removes every factor of 2 and 5 from $x$.
Example:
- $40 = 2^3\cdot5$
- reduced part is $1$.
- $72=2^3\cdot9$
- reduced part is $9$.
Prefix products
prefix[i] = prefix[i - 1] * reduce_25(i)
Stores
$$\prod_{k=1}^i R(k)\pmod{100000}.$$
This lets us evaluate huge products quickly.
Recursive function g(n)
The recursion arises because multiples of 5 contribute additional stripped factors.
ans = (ans * g(n // 5)) % MOD
captures the next level of removed 5s.
Depth is only about 18 for $10^{12}$.
6. Small checks
Example: $9!$
$$9! = 362880.$$
Removing trailing zero:
$$36288.$$
The program gives:
$$f(9)=36288.$$
Correct.
Example: $10!$
$$10!=3628800.$$
Removing trailing zeros:
$$36288.$$
Correct.
Example: $20!$
$$20!=2432902008176640000.$$
Removing trailing zeros gives:
$$17664.$$
Correct.
7. Final verification
The result must:
- be nonzero modulo $10$,
- have exactly five digits when leading zeros are included if necessary,
- be congruent to an odd multiple after cancellation of powers of 10.
Running the algorithm gives:
$$16576.$$
Thus the last five nonzero digits of $10^{12}!$ are:
Answer: 16576