【问题标题】:What makes this prime factorization so efficient?是什么让这个素数分解如此有效?
【发布时间】:2015-07-27 12:06:02
【问题描述】:

我一直在做一些 Project Euler 问题来学习/练习 Lua,而我最初找到最大素因数 n 的快速而肮脏的方法非常糟糕,所以我查阅了一些代码以了解如何其他人正在这样做(试图了解不同的分解方法)。

我遇到了以下问题(最初是在 Python 中 - 这是我的 Lua):

function Main()
    local n = 102
    local i = 2
    while i^2 < n do
        while n%i==0 do n = n / i end
        i = i+1
    end
    print(n)
end

这在 非常 很短的时间内 - 几乎立即产生了巨大的数字。我注意到的关于算法的事情是我不会猜到的:

  • n = n / i

这似乎存在于所有体面的算法中。我用较小的数字在纸上计算出来,我可以看到它使数字收敛,但我不明白为什么这个操作会收敛到最大的素因子上。

谁能解释一下?

【问题讨论】:

  • 尝试使用较大的素数,例如 n = 10^18 + 3。当有更有效的因式分解算法可用时,算法仍然是 O(sqrt(n))
  • 一个相当简单的算法是 Pollard 的 rho 算法,预期复杂度为 O(n^(1/4))

标签: algorithm prime-factoring


【解决方案1】:

在这种情况下,i 是主要因素候选者。考虑一下,n 由以下素数组成:

n = p1^n1 * p2^n2 * p3^n3

i 到达p1 时,语句n = n / i = n / p1 会删除一次出现的p1

n / p1 = p1^(n-1) * p2^n2 * p3^n3

只要n 中有p1s,内部while 就会迭代。因此,在迭代完成后(当i = i + 1 被执行时),所有出现的p1 都已被删除,并且:

n' =  p2^n2 * p3^n3

让我们跳过一些迭代,直到 i 达到 p3。那么剩下的n就是:

n'' = p3^n3

在这里,我们发现代码中的第一个错误。如果 n3 为 2,则外部条件不成立,我们仍然使用 p3^2。应该是while i^2 &lt;= n

和以前一样,内部的while 删除了所有出现的p3,给我们留下了n'''=1。这是第二个错误。它应该是 while n%i==0 and n&gt;i(不确定 LUA 语法),它保留了最后一次出现。

所以上面的代码适用于所有数字n,其中最大的素数只出现一次,通过连续删除所有其他因素。对于所有其他数字,上述更正也应使其正常工作。

【讨论】:

    【解决方案2】:

    这消除了n 之外的所有已知较小的素因数,因此n 变得更小,并且可以更早地达到sqrt(n)。这提高了性能,因为您不再需要将数字计算为原始 N 的平方根,例如如果 n 是一百万,它由 2 和 5 组成,并且对所有已知素数的天真查询需要检查所有质数最高为 1000,而将其除以 2 得到 15625,然后除以 5 得到 1(顺便说一下,您的算法将返回 1! 要修复,如果您的循环以 n=1 退出,请返回i 代替。)分两步有效地分解大数字。但这仅适用于“普通”数字,它们有一个高质数分母和一堆较小的数,但分解一个数字 n=p*qpq 都是质数并且接近不会能够从这种提升中受益。

    n=n/i 行有效,因为如果您正在寻找除 i 之外的另一个素数,那么您当前发现您是一个除数,根据素数的定义,结果也可以被该素数整除。在这里阅读:https://en.wikipedia.org/wiki/Fundamental_theorem_of_arithmetic。这也仅适用于您的情况,因为您的 i 从 2 向上运行,因此您首先除以素数,然后除以它们的复合数。否则,如果您的数字将 3 作为最大素数,也可以被 2 整除,并且您首先检查 6,那么您将破坏仅除以素数的原则(例如,如果您首先除以 6,则使用 72,你最终会得到 2,而答案是 3) 意外除以最大素数的合数。

    【讨论】:

      【解决方案3】:

      这个算法(修正后)需要 O(max(p2,sqrt(p1))) 步来找到 n 的素因子分解,其中 p1 是最大的素因子,p2 是第二大的素因子。在重复最大素因数的情况下,p1=p2。

      Knuth 和 Trabb Pardo 研究了此函数的行为 "Analysis of a Simple Factorization Algorithm" Theoretical Computer Science 3 (1976) 321-348。他们反对通常的分析,例如计算最大为 n 的整数时所采取的平均步数。尽管一些具有大素因数的数字提高了平均值,但在密码学上下文中,可能更相关的是一些百分位数非常低。例如,44.7% 的数字满足max(sqrt(p1),p2)&lt;n^(1/3),1.2% 的数字满足max(sqrt(p1),p2)&lt;n^(1/5)

      一个简单的改进是在找到一个新的素因子后测试余数的素数。测试一个数是否是素数是非常快的。通过避免 p2 和 sqrt(p1) 之间的试验划分,这减少了 O(p2) 的时间。第二大素数的中位数约为 n^0.21。这意味着使用这种对试除法的改进可以快速(在几处理器秒内)分解许多 45 位数字。相比之下,根据一个模型,对两个素数的乘积进行 Pollard-rho 分解平均需要 O(sqrt(p2)) 步。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-14
        • 2016-02-15
        • 1970-01-01
        • 1970-01-01
        • 2014-08-12
        • 1970-01-01
        • 2016-05-26
        • 1970-01-01
        相关资源
        最近更新 更多