1

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?

Michael Laszlo
  • 12,009
  • 2
  • 29
  • 47
qwr
  • 9,525
  • 5
  • 58
  • 102
  • 1
    When you use `range(100000, 200001)`, the last number you multiply by is `2`. – Barmar Dec 24 '15 at 02:58
  • But when you do `range(1, 100001)`, the last number is `1`. – Barmar Dec 24 '15 at 03:00
  • There are also lots of different numbers in between. – Barmar Dec 24 '15 at 03:00
  • If you just want the last 5 digits, it should be `s = s % 10**5` – Barmar Dec 24 '15 at 03:15
  • @Barmar Your first comment seems to make sense. But I have edited the question to include a new problem – qwr Dec 24 '15 at 03:27
  • Is there a smaller range that you think should have the same property, so we can try doing it by hand to see all the intermediate results? – Barmar Dec 24 '15 at 03:50
  • I don't see how changing the code to use variables makes any difference. It still has the same problem. – Barmar Dec 24 '15 at 03:51
  • @Barmar I believe the last 2 digits of `f(1,100)**10` should equal the last two digits of `f(1,1000)` – qwr Dec 24 '15 at 03:54
  • Change the function to print the value of `s` each time through the loop, so you can see where it diverges. – Barmar Dec 24 '15 at 03:55
  • You're on your own, I'm not going to try to do 1,000 steps on paper. – Barmar Dec 24 '15 at 03:56
  • I still don't understand what `s = s % 10**10` is for. The question says "last 5 digits", but that gets the last 10 digits. – Barmar Dec 24 '15 at 03:57
  • @Barmar It is extra padding that does not really serve a purpose – qwr Dec 24 '15 at 03:58
  • `I believe the last 2 digits of f(1,100)**10 should equal the last two digits of f(1,1000)` The last 2 digits of `f(1, 100) ** 10` are the same as `100! ^ 10` which gives 76. The last 2 digits of `f(1, 1000)` is the same as `1000!` gives 72. I really think your assumptions are wrong – André Fratelli Dec 24 '15 at 04:07
  • @AndréFratelli yes, it must be my aggressive division by 10 – qwr Dec 24 '15 at 04:34
  • Your division by 10 takes zeros, not non-zero digits. I'm not saying this is a problem with your implementation, I'm saying that, _mathematically_ speaking, one case gives 76 and the other 72, so your assumption is wrong – André Fratelli Dec 24 '15 at 04:39
  • @AndréFratelli yes, but there must be some way to find the last digits of 1 to 1000 (or 10000000000) without multiplying out – qwr Dec 24 '15 at 04:53
  • @qwr If there was a method to find the last `N` digits of a factorial without multiplying, nobody would be multiplying to compute factorials, would they? – André Fratelli Dec 24 '15 at 04:56
  • @AndréFratelli my bet would be if I removed all factors of 2 and 5, both of my implementations would work properly – qwr Dec 24 '15 at 05:05
  • But that's a theorem you need to prove then.. You don't need help with python, you need help with math – André Fratelli Dec 24 '15 at 05:07

1 Answers1

1

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.

Michael Laszlo
  • 12,009
  • 2
  • 29
  • 47
  • I'm claiming for first that the last digit(s) will be the same (which it is, since 10 and 20 are divisible by 10^1,so 8) and my second claim is specifically the last digit(s) of 10*10^n = 10^(n+1) for the last n digits – qwr Dec 24 '15 at 03:44
  • `10 * 10 ^ n = 10 ^ (n + 1)` for **all** digits, not just the last – André Fratelli Dec 24 '15 at 03:47
  • The final 8 is a coincidence. Consider 3 and 6: they're both divisible by 3, but 1*2*3 = 6 and 4*5*6 = 120. – Michael Laszlo Dec 24 '15 at 03:48
  • But I agree with @MichaelLaszlo, I think your assumptions are wrong – André Fratelli Dec 24 '15 at 03:49
  • @MichaelLaszlo The 8 is not a coincidence, as I am working in base 10 and mutliplying 1 to 10 involves the same last digit as 10 to 20 – qwr Dec 24 '15 at 03:50
  • 1
    The last digits of the terms are the same, but that doesn't mean the last non-zero digit of the product will be the same. Compare 2*5 = 10 against 12*15 = 180. And 22*25 = 550. – Michael Laszlo Dec 24 '15 at 03:56
  • @MichaelLaszlo I think he's only claiming this equivalence for the special case where the start of the range is `10**n+1` – Barmar Dec 24 '15 at 04:01
  • @MichaelLaszlo I think you are getting closer now...numbers that are multiples of 2s and 5s are probably getting extra zeros removed! – qwr Dec 24 '15 at 04:06
  • I still don't get it, so what if they get their zeros removed? Why do you claim the last non-zero digits are the same? Please be clear – André Fratelli Dec 24 '15 at 04:10
  • @AndréFratelli the examples Michael Laszlo gave in his answer aren't applicable, but his last comment seems more of an answer. I hope someone has the correct method to do what I intended – qwr Dec 24 '15 at 04:35