Project Euler 5 in Python - How can I optimize my solution?

后端 未结 20 1107
醉梦人生
醉梦人生 2020-11-30 08:00

I\'ve recently been working on Project Euler problems in Python. I am fairly new to Python, and still somewhat new as a programmer.

In any case, I\'ve ran into a sp

20条回答
  •  半阙折子戏
    2020-11-30 08:51

    Two different types of solutions have been posted here. One type uses gcd calculations; the other uses prime factorization. I'll propose a third type, which is based on the prime factorization approach, but is likely to be much faster than prime factorization itself. It relies on a few simple observations about prime powers -- prime numbers raised to some integral exponent. In short, it turns out that the least common multiple of all numbers below some number n is equal to the product of all maximal prime powers below n.

    To prove this, we begin by thinking about the properties that x, the least common multiple of all numbers below n, must have, and expressing them in terms of prime powers.

    1. x must be a multiple of all prime powers below n. This is obvious; say n = 20. 2, 2 * 2, 2 * 2 * 2, and 2 * 2 * 2 * 2 are all below 20, so they all must divide x. Likewise, 3 and 3 * 3 are both below n and so both must divide x.

    2. If some number a is a multiple of the prime power p ** e, and p ** e is the maximal power of p below n, then a is also a multiple of all smaller prime powers of p. This is also quite obvious; if a == p * p * p, then a == (p * p) * p.

    3. By the unique factorization theorem, any number m can be expressed as a multiple of prime powers less than m. If m is less than n, then m can be expressed as a multiple of prime powers less than n.

    Taken together, the second two observations show that any number x that is a multiple of all maximal prime powers below n must be a common multiple of all numbers below n. By (2), if x is a multiple of all maximal prime powers below n, it is also a multiple of all prime powers below n. So by (3), it is also a multiple of all other numbers below n, since they can all be expressed as multiples of prime powers below n.

    Finally, given (1), we can prove that x is also the least common multiple of all numbers below n, because any number less than x could not be a multiple of all maximal prime powers below n, and so could not satisfy (1).

    The upshot of all this is that we don't need to factorize anything. We can just generate primes less than n!

    Given a nicely optimized sieve of eratosthenes, one can do that very quickly for n below one million. Then all you have to do is find the maximal prime power below n for each prime, and multiply them together.

    prime_powers = [get_max_prime_power(p, n) for p in sieve(n)]
    result = reduce(operator.mul, prime_powers)
    

    I'll leave writing get_max_prime_power as an exercise. A fast version, combined with the above, can generate the lcm of all numbers below 200000 in 3 seconds on my machine.

    The result is a 86871-digit number!

提交回复
热议问题