Here is a simple program to find the last several non-zero digits of the product of the numbers 1 through 105, removing trailing zeros along the way:
def f(a, b):
s = 1
for i in range(a, b+1):
s *= i
while not s % 10:
s //= 10
s = s % 10**10
return s
f(1, 10**5)
and f(10**5+1, 2*10**5)
do not produce the same last 5 digits, though mathematically they should.
Additionally, f(1, 10**5)**10
does not produce the same ending digits as f(1, 10**6)
.
Where is the problem here and what is the correct implementation?
Your code correctly finds the last ten digits after the rightmost zero digits are discarded. Your belief that the code is incorrect rests on a pair of fallacious claims.
First you claim that the product of 1 through n, or n!, should have the same non-zero digits as the product of n+1 through 2n, which is:
(n+1)*(n+2)*...*(2n) = (2n)! / n!
In saying that the non-zero digits of n! and (2n)!/n! should be equal, you are implying that for some constant k, we have:
10^k * n! = (2n)! / n!
But this is false in general. Consider this counterexample:
20! = 2432902008176640000
40! / 20! = 335367096786357081410764800000
Your second claim is that n! raised to the power of 10 is the same as (10n)!. This is false. In general, it is not true that:
(n!)^k = (kn)!
Counterexample:
3!^10 = 60466176
30! = 265252859812191058636308480000000
I generated these figures with the following function:
def series(start, end):
x = start
for i in range(start + 1, end + 1):
x *= i
return x
For example, to see that the product of 1 through 100 does not have the same non-zero digits as the product of 101 through 200, execute:
print(series(1, 100))
print(series(101, 200))
The first yields a number whose last five digits after removing the rightmost zeros are 16864
. For the second, they are 02048
.