素数问题

时间:2009-12-09 22:07:15

标签: java primes

我正在尝试编写一个程序来找到一个非常大的最大素数因子,并尝试了几种不同的成功方法。到目前为止我发现的所有这些都令人难以置信地缓慢。我有一个想法,我想知道这是否是一个有效的方法:

long number = input;

while(notPrime(number))
{
    number = number / getLowestDivisiblePrimeNumber();
}

return number;

这种方法需要输入,并且会执行以下操作:

200 - > 100 - > 50 - > 25 - > 5(返回)

90 - > 45 - > 15 - > 5(返回)

它将currentNum重复除以最小的可分数(最常见的是2或3),直到currentNum本身为素数(没有可分的素数小于currentNum的平方根),并假设这是最大的素数因子。原始输入。

这总是有效吗?如果没有,有人可以给我一个反例吗?

-

编辑:非常大,我的意思是大约2 ^ 40,或10 ^ 11。

6 个答案:

答案 0 :(得分:22)

该方法可行,但速度很慢。 “你的数字有多大?”确定要使用的方法:

答案 1 :(得分:16)

这将始终有效,因为Unique Prime Factorization Theorem

答案 2 :(得分:3)

当然它会起作用(见Mark Byers' answer),但对于“非常大”的输入,它可能需要太长时间。你应该注意到你对getLowestDivisiblePrimeNumber()的调用隐藏了另一个循环,因此它运行在O(N ^ 2),并且根据你的意思“非常大”它可能必须在BigNums上运行这将是缓慢的。

你可以通过注意你的算法不需要检查小于找到的最后一个因子来加快它的速度。

答案 3 :(得分:2)

您正在尝试查找号码的prime factors。你提出的建议会起作用,但对于大数字来说仍然会很慢......你应该感谢这一点,因为大多数现代安全都是基于这是一个难题。

答案 4 :(得分:1)

通过我刚刚做的快速搜索,使用椭圆曲线方法计算数字的最快的已知方法。

您可以尝试在此演示版中输入您的电话号码:http://www.alpertron.com.ar/ECM.HTM

如果这说服了你,你可以尝试窃取代码(这没什么好玩的,它们提供了链接!)或者在其他地方阅读理论。这里有一篇关于它的维基百科文章:http://en.wikipedia.org/wiki/Lenstra_elliptic_curve_factorization但是我太愚蠢了解它。谢天谢地,这是你的问题,不是我的问题! :)

答案 5 :(得分:0)

项目Euler的事情是,通常有一种明显的暴力方法来解决这个问题,这种方法将会永远存在。随着问题变得更加困难,您需要实施更聪明的解决方案。

解决此问题的一种方法是使用始终找到数字的最小(正整数)因子的循环。当一个数字的最小因子是那个数字时,那么你就找到了最大的素数因子!

详细的算法描述:

您可以通过保留三个变量来实现此目的:

您想要考虑的数字(A) 现在的除数店(B) 最大的除数商店(C)

最初,让(A)成为您感兴趣的数字 - 在这种情况下,它是600851475143.然后让(B)为2.有条件检查(A)是否可以被(B)整除。如果它是可分的,则将(A)除以(B),将(B)重置为2,然后返回检查(A)是否可被(B)整除。否则,如果(A)不能被(B)整除,则将(B)增加+1,然后检查(A)是否可被(B)整除。运行循环直到(A)为1.返回的(3)将是600851475143的最大质数。

有许多方法可以使这更有效 - 而不是递增到下一个整数,你可以增加到下一个必然的素数整数,而不是保持一个最大的除数存储,你可以只返回当前的数字只有除数本身。但是,我上面描述的算法无论如何都会在几秒钟内运行。

python中的实现如下: -

def lpf(x):
        lpf = 2;
        while (x > lpf):
                if (x%lpf==0):
                        x = x/lpf
                        lpf = 2
                else:
                        lpf+=1;
        print("Largest Prime Factor: %d" % (lpf));

def main():
        x = long(raw_input("Input long int:"))
        lpf(x);
        return 0;

if __name__ == '__main__':
    main()

示例:让我们使用上述方法找到最大的素数因子105.

设(A)= 105.(B)= 2(我们总是从2开始),我们还没有(C)的值。

(A)可以被(B)整除吗?编号增量(B)+1:(B)= 3.(A)是否可被(B)整除?是。 (105/3 = 35)。到目前为止发现的最大除数是3.令(C)= 3.更新(A)= 35.重置(B)= 2.

现在,(A)可以被(B)整除吗? No.增量(B)+1:(B)= 3.(A)是否可被(B)整除? No.增量(B)+1:(B)= 4.(A)是否可以被(B)整除?编号增量(B)+1:(B)= 5.(A)是否可以被(B)整除?是。 (35/5 = 7)。我们之前发现的最大除数存储在(C)中。 (C)目前是3. 5大于3,所以我们更新(C)= 5.我们更新(A)= 7。我们重置(B)= 2。

然后我们重复(A)的过程,但我们将继续递增(B)直到(B)=(A),因为7是素数并且没有除了它本身和1之外的除数。(我们已经可以停止当(B)>((A)/ 2)时,因为你不能有大于一半数的整数除数 - 任何数的最小可能除数(除1之外)都是2!)

所以在这一点上我们返回(A)= 7。

尝试手动完成其中的一些操作,你就会明白这个想法