【问题标题】:Project Euler 3 - Why does this method work?Project Euler 3 - 为什么这种方法有效?
【发布时间】:2012-09-18 06:59:00
【问题描述】:

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

【问题讨论】:

  • 函数返回6857,运行方便。
  • 它不适用于 600851475149。
  • 是的,看起来像是一次性破解 Project Euler 的特定问题

标签: primes prime-factoring


【解决方案1】:

此函数通过查找其输入的连续因子来工作。它找到的第一个因素必然是素数。找到一个素因数后,将其从原始数中除掉,然后继续该过程。当我们将它们全部除掉(留下 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 项目来说已经足够了。

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

【讨论】:

    【解决方案2】:

    考虑它如何解决 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 * 的正确答案(100,000 之后的下一个最大素数。

    【讨论】:

      【解决方案3】:

      实际上没有人回答您的问题。 for 循环依次测试每个数字 i。当in 的因子时,while 循环的测试成功;在这种情况下,它会减少 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 必须是素数。因子按递增顺序插入,因此输出列表中的最后一个因子将是最大的,这就是您想要的。

      【讨论】:

      • 它非常接近标准整数分解。当然,测试偶数是浪费,但从技术上讲,测试每个合数也是如此。该解决方案只需要一个适当的上限即可正常工作。您刚刚描述了一些优化,而不是完全不同的方法。
      • @nneonneo 错了,你的反对票(我认为是)是不必要的。我会解释的。 “只需要适当的上限”是错误的,因为当其因子被划分时,数字本身会发生变化。所以上限也必须改变。但是对于 range,上限是 pre 指定的。 accepted answer 在这方面也是错误的。我已经编辑了答案以改进格式,因此投反对票的人有机会撤消他们的反对票。
      猜你喜欢
      • 2016-09-12
      • 1970-01-01
      • 2013-12-18
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 2021-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多