项目欧拉3 - 为什么这种方法有效?

时间:2012-09-26 15:32:47

标签: primes prime-factoring

13195的主要因素是5,7,13和29。 600851475143的最大主要因素是什么?

我以自己的方式在Project Euler上解决了这个问题,这很慢,然后我在某人的github帐户上找到了这个解决方案。我无法弄清楚它为何起作用。为什么删除了许多因素,等于索引?有什么见解吗?

def Euler3(n=600851475143):
    for i in range(2,100000):
        while n % i == 0:
            n //= i
            if n == 1 or n == i:
                return i

3 个答案:

答案 0 :(得分:7)

此功能通过查找其输入的连续因子来工作。它找到的第一个因素必然是素数。找到素数因子后,将其除以原始数字,然后继续处理。当我们将它们全部分开(留下1或当前因子(i))时,我们得到了最后一个(最大的)。

我们在这里添加一些跟踪代码:

def Euler3(n=600851475143):
    for i in range(2,100000):
        while n % i == 0:
            n //= i
            print("Yay, %d is a factor, now we should test %d" % (i, n))
            if n == 1 or n == i:
                return i

Euler3()

这个输出是:

$ python factor.py
Yay, 71 is a factor, now we should test 8462696833
Yay, 839 is a factor, now we should test 10086647
Yay, 1471 is a factor, now we should test 6857
Yay, 6857 is a factor, now we should test 1

确实,对于一般解决方案,范围的顶部应该是n的平方根,但是对于python,调用math.sqrt会返回浮点数,所以我认为原始程序员正在服用一个懒惰的捷径。该解决方案一般不起作用,但对于Euler项目来说已经足够了。

但算法的其余部分是合理的。

答案 1 :(得分:3)

考虑它如何解决n = 20:

iteration i=2
  while true (20 % 2 == 0)
    n = n//2 = 20//2 = 10
    if (n == 1 or n == 2) false
  while true (10 % 2 == 0)
    n = n//2 = 10//2 = 5
    if (n == 1 or n == 2) false
  while false (5 % 2 == 0)
iteration i = 3
  while false (5 % 3 == 0)
iteration i = 4 
  while false (5 % 4 == 0)
iteration i = 5
  while true (5 % 5 == 0)
    n = n//5 = 5//5 = 1
    if (n == 1 or n == 5) true
      return i, which is 5, which is the largest prime factor of 20

它只是删除因子,并且因为它已经删除了多个素因子(while循环),所以i的许多值实际上只是浪费了精力。在循环中有机会做任何事情的i的唯一值是i的素数值。 n == i测试涵盖25个数字的情况,它们是素数的正方形。 但范围似乎有限。它不能给出2 *(10万之后的下一个最大素数)的正确答案。

答案 2 :(得分:1)

没有人真正回答过你的问题。 for循环依次测试每个数字i。当whilei的因素时,n循环的测试成功;在这种情况下,它会减少n,然后通过将i1n进行比较来检查是否已完成。如果while不止一次划分if,则测试为i(而不仅仅是n)。

虽然很聪明,但这并不是通过试验划分整数分解的方式;如果n的因子大于100000,它也无效。我的博客上有explanation。这是我的函数版本,它列出了n的所有因素,而不是最大的因素:

def factors(n):
    fs = []
    while n % 2 == 0:
        fs += [2]
        n /= 2
    if n == 1:
        return fs
    f = 3
    while f * f <= n:
        if n % f == 0:
            fs += [f]
            n /= f
        else:
            f += 2
    return fs + [n]

此函数分别处理2,然后仅尝试奇数因子。它也不会对因子设置限制,而是在因子大于剩余n的平方根时停止,因为此时n必须是素数。因子按递增顺序插入,因此输出列表中的最后一个因子将是最大的,这是您想要的那个。