在课堂上我们发现了这个编程问题,目前我们还不知道如何解决它。
给出正整数
n
。众所周知n = p * q
,其中p
和q
是素数,p<=q
和|q-k*p|<10^5
对于某些给定的正整数k
。您必须找到p
和q
。
输入:
35 1
121 1
1000730021 9
输出:
5 * 7
11 * 11
10007 * 100003
这不是家庭作业,我们只是想解决一些有趣的问题。如果您有一些想法,请在此发布,以便我们尝试一下,谢谢。
答案 0 :(得分:2)
对于你在这里讨论的数字,最快的保理方法是(可能)使用Eratosthenes的Sieve来生成大约接近数字的平方根的素数,然后使用试验除法来找到哪个一个人是除数。
已经为更多的数字发明了相当多的保理方法。您可能希望Google使用“Fermat的保理方法”,“Pollard Rho”,“Brent方法”,“Lenstra椭圆曲线”,“多重多项式二次筛”和“通用数字筛”。我已经列出了(粗略地)复杂性的升序和能够考虑更大数字的能力。我们是否应该提及通用数字现场筛网是值得怀疑的 - 虽然它是目前已知的最有效的方法,因为它非常大,但它只适用于大型机器 - 大约110位左右,MPQS更快,但要考虑GNFS更快的大数字,你需要比典型的桌面或服务器可以支持更多的内存(想想一个TB的RAM作为最低起点,但可能更多)。 / p>
答案 1 :(得分:2)
我使用ECM方法来计算大整数。它是已知最有效的算法之一。如果你想了解算法是如何工作的,那么你有很多阅读要做,但是如果你想用它来做你的研究,有些人已经实现了它。例如,您可以获得这些开源软件包:用于C / C ++的GMP-ECM或用于Python的Pyecm。
$ python
>>> import math
>>> import pyecm
>>> n = 1000730021
>>> list(pyecm.factors(n, False, False, 2 * math.log(math.log(n)), 1.0))
[10007, 100003]
答案 2 :(得分:1)
n = p * q
|q-k*p|<10^5
以n
和k
作为输入。因此
q-k*p=a
带
-10^5<=a<=10^5
将q-k*p=a
乘以q
并将p*q
替换为n给出
q^2-a*q-k*n=0
使用
解决每个a
的二次方程
-10^5<=a<=10^5`
并检查q
是否划分n
。
求解二次方程可以在多项式时间内完成,这对于求解2*10^5+1
方程也是如此。对于n
和k
的小值,以及n
和k
的较大值,有更好的算法。
正如ypercube所提到的,人们只需检查方程式
a^2+4*k*n
是一个正方形。
答案 3 :(得分:0)
n = p * q且| q-k * p | <10 ^ 5,其中n和k作为输入给出。因此q-k * p = a, 用-10 ^ 5 <= a <= 10 ^ 5 将q-k * p = a乘以q,将p * q代入n得到 C 1-4 2-A * Q-K * N = 0。 用-10 ^ 5&lt; = a&lt; = 10 ^ 5求解每个a的这个二次方程,并检查q是否除n。 求解二次方程可以在多项式时间内完成,这对于求解2 * 10 ^ 5 + 1方程也是如此。对于n和k
的小值,有更好的算法p在intervall中
[(sqrt(k*n+2500000000)-50000)/k,(sqrt(k*n+2500000000)+50000)/k]
因此,您只能检查p的10 ^ 5 / k值。 q在intervall中
[sqrt(k*n+2500000000)-50000,sqrt(k*n+2500000000)+50000]
总是包含大约10 ^ 5个inegers
答案 4 :(得分:-1)
您可以使用http://qurancode.com中基于YAFU的基于GUI的版本来尝试更大的示例。 YAFU的主要好处是它的自适应特性,可以在分解时自动切换算法。使用Windows 7/8/10的GUI版本确实是最好,最轻松的方式。
只需单击红色心形包围的黄色PI符号:)