我已经写了这段代码,但是计算起来很费时间……你能帮我找出一种有效的方法吗?
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);
}
这种蛮力方法在复杂性方面非常庞大......这个问题有没有更好的可行解决方案?
到目前为止,还没有人提出一种更快的算法。这并不一定意味着没有,因为另一方面也没有证明不可能更快地做到这一点。
您可能需要考虑的一项优化是,不必搜索 n/2,当达到 sqrt (n) 时,您已经可以停止。
...如果您真的想返回“克里斯”评论中已经提到的所有候选人的列表,请务必为您的号码选择不同的存储位置。
编辑:
正如我被告知的那样,有相当多的算法可用,就时间复杂度而言,它们的运行速度可能比您询问的算法要快一点,可能需要比上面给出的简短评论添加更多的单词。
虽然除了在第一次将其划分为奇数后以 2 的步长运行循环来保护一些计算时间的最明显可能性之外,还有一些其他可用的技巧我没有在上面给出的答案中提到它们明显更快.
导致这个决定的主要原因是,虽然例如将迭代次数减少 2 倍似乎是一个巨大的胜利,但与运行时的预期增长相比,随着数量的增长,增益以常数变得如此之小,以至于在复杂性理论中甚至根本不会产生任何差异,并且可以说两种算法具有(几乎)相同的时间复杂度。
即使有可能在原始算法的运行时间中获得数千亿倍的恒定增益,它们之间仍然没有任何区别。
数字越大,任何常数的影响就越小,无论它在运行时间方面可能达到多少,如果它也随着你所处理的数字的大小而迅速增长。
就时间复杂度而言,一个非常特殊的障碍通常被认为是实际可行和不可能之间的边界,即所谓的polynomial
运行时间。
这意味着即使运行时可能会随着增长而急剧增长n
,但仍然可以用常数指数来描述这种增长k
,这样运行时就是周围的东西n^k
。
另一方面,没有polynomial
运行时的算法不能用任何指数来衡量,你可能想要让它变得多大。
为了举例说明为什么这种差异可能真的很重要,让我们看一下两个虚构的算法。第一个具有多项式运行时,比如说n^10
,另一个说这个具有运行时n!
。
虽然它对于小数字似乎并不坏,假设 n 只是 10 这里算法第一个需要10^10 = 10000000000
时间单位,而只有3628800
单位我们的第二个算法似乎运行得更快。
我们的算法二的问题是,与算法一相比,它的运行时间会增长得更快。在n=100
你得到类似的东西:100000000000000000000
对于算法一,它已经类似于93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
算法二了。
进一步推进边界,n=1000
我们最终得到:算法一,1000000000000000000000000000000
而我们的第二个算法将采用类似402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
.
不信就自己算吧。该bc
手册甚至包含如何实现阶乘函数的示例。
但是不要在数数字时感到头晕......知道我们必须将多少个尾随零添加到10才能得到乘以我们宇宙年龄的因子以获得如此大的跨度可能会很有趣即使我们以普朗克时间为单位进行测量。不幸的是我不知道。
所有这一切的有趣之处在于,直到今天还没有任何已知的算法可以及时执行因式分解polynomial
。
由于它本身不仅是一个有趣的研究领域,实际上不可能分解大整数也在当今广泛使用的 RSA 公钥加密算法中发挥着重要作用,因此几乎自然已经有很多研究在这个区域。
发现算法(没有打破已经提到的障碍)比你想象的算法运行得更快。
正如“Jim Balter”在他的评论中已经正确注释的那样,你可能想看看引用的文章(见:http ://en.wikipedia.org/wiki/Integer_factorization#General-purpose )看看方法其他人已经想出了。
“Jim”也提到的这篇文章可能是另一个有趣的资源:(参见:最快的分解算法是什么?)
另一个值得关注的有趣链接可能是过去几年的 RSA 因式分解挑战获胜者名单,以便以某种方式了解今天可行和几乎不可能之间的边界在哪里。(http://en.wikipedia.org/wiki/RSA_Factoring_Challenge)