计算一个整数的所有因子的最快算法是什么?

16

我已经写好了这段代码,但计算时间很长... 你能帮我找到一种更高效的方法吗?

int tag;
int* factors(int n)
{
    int a[1000000];
    for(int i=1;i<=n/2;i++)
        if(n%i==0)
            a[++tag]=i;
    a[++tag]=n;
    return(a);
}

这种暴力方法在复杂度方面非常笨重... 有没有更好的可行解决方案?


20
Shor's Algorithm(肖尔算法):一种用于量子计算机上因式分解大整数的算法,由Peter Shor在1994年提出。该算法被认为是对称性的突破,因为传统的计算机需要指数级时间才能完成这项任务,而肖尔算法只需多项式时间。该算法的实际应用包括破解RSA加密等密码学问题。 - Mysticial
9
当函数结束时,返回指向已释放内存的指针,我明白了。 - chris
1
快速搜索返回以下内容:http://en.wikipedia.org/wiki/Integer_factorization - lenik
1
只需要获得一台量子计算机,Mysticial... - Kirby
1
你花了多少时间思考它? - Jim Balter
1个回答

12

目前还没有人提出更快的算法。这不一定意味着没有更快的算法,因为另一方面也尚未证明无法更快地完成。

您可能想考虑的一种优化是,无需搜索到 n/2,只要到达 sqrt(n) 就可以停止。

... 确保如果您真的想返回找到的所有候选项列表,则选择不同的存储位置,如 "chris" 评论中所述。

编辑:

由于有相当多的算法可用,这些算法在时间复杂度上可能比您要求的算法运行得稍微快一些,因此我们可能需要添加一些比上面短评论中给出的更多的单词。

虽然除了在首先将其降为奇数后仅以步长 2 运行循环这种最明显的节省计算时间的方法外,还有一些其他技巧可用,但我没有在上面的答案中提到它们是“实质性”更快的。

导致做出这个决定的主要原因是,尽管例如通过将迭代次数减少一半似乎在与增长数字的预期运行时间的比较中获得了很大的胜利,但在复杂度理论中,如果增益以常数衡量,则增益变得如此之小,以至于根本没有任何区别,并且两种算法将被认为拥有(几乎)相同的时间复杂度。

即使您能够获得原始算法的运行时间的常数增益多达数十亿倍,两者之间仍然不会有任何区别。

随着数字的增长,无论您可能想象得到的常数有多大,它对运行时间的影响都越来越小,如果它也随着您正在处理的数字的大小快速增长。

在时间复杂度方面通常被视为实际可行和完全不可能之间的一个非常特殊的界限是所谓的多项式运行时间。

这意味着尽管运行时间可能随着增加的n而急剧增长,但仍然可以使用常数指数k描述这种增长,使得运行时间约为n^k

另一方面,没有多项式运行时间的算法无法用任何指数来测量其复杂度,无论您希望它有多大。

为了举一个例子,说明这种差异为什么真的很重要,让我们看一下两个想象中的算法。第一个具有多项式运行时间,比如n^10,而另一个则具有运行时间n!

虽然对于小的数字来说似乎还不错,假设n只有10,算法一需要10 ^ 10 = 10000000000 个时间单位,而我们的第二个算法仅需 3628800 个时间单位,似乎运行速度要快得多。

我们的第二个算法问题在于,与算法一相比,它的运行时间将急剧增长。当n=100时,算法一需要100000000000000000000个时间单位,而算法二已经达到93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000个时间单位。

当我们将n=1000带入时,我们得到了更进一步的结果:第一个算法为1000000000000000000000000000000,而第二个算法可能需要大约402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

如果你不相信,就自己计算一下。 bc 手册甚至包含了如何实现阶乘函数的示例。

但是在数位计算时不要头晕眼花……即使我们以普朗克时间为单位进行测量,要添加多少个尾随零才能得到我们的宇宙年龄的倍数,以获得如此长的时间跨度也可能是有趣的。不幸的是我不知道。

所有这些的有趣之处在于,直到今天还没有任何已知的算法可以在 多项式 时间内执行因数分解。

由于不仅本身是一个有趣的研究领域,而且大整数因子分解的实际不可能性在今天广泛使用的 RSA 公钥加密算法中也发挥着重要作用,因此几乎自然地,这个领域已经有了很多研究。

发现比你想象中的算法稍微快一点的算法。

正如“Jim Balter”在他的评论中已经正确地注释的那样,您可能想查看所引用的文章(参见:http://en.wikipedia.org/wiki/Integer_factorization#General-purpose)以查看其他人已经提出的方法。

另一篇有趣的文章也可能是一个有用的资源:(参见:What is the fastest factorization algorithm?

另一个有趣的链接是查看过去几年 RSA 因子分解挑战赛的获胜者列表,以便在某种程度上了解可行和几乎不可能之间的边界当前在哪里。 (http://en.wikipedia.org/wiki/RSA_Factoring_Challenge


1
好的...这不是一个大问题。 我只是忘记把存储位置设为全局了... - Biswajit
1
你可以通过仅尝试除以质数来改进所示算法——质数比合数少得多。 - Jonathan Leffler
1
除此之外,还有http://en.wikipedia.org/wiki/Integer_factorization#General-purpose...因此,比OP的代码快得多的算法也存在。 - Jim Balter
我强烈怀疑您的假设是否真的成立,因为OP所涉及的数字范围相当小,足以按照他的意图处理这些值。即使允许比他传递的UINT_MAX更广阔的范围——仔细观察会发现他只是传递了一个int!运行时间包括进程启动时间报告如下:real m0.013s user0m0.008s sys 0m0.004s,这在我看来似乎非常快速和合理。 - mikyra
1
耸肩不知道 - OP说:“这种暴力方法在复杂性方面非常繁重...有没有更好的可行解决方案?”我想他可能对复杂性(理论)感兴趣。 - mikyra
显示剩余13条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接