我想让我的程序找到数字600851475143的最大素因子。例如,13195的素因子是5,7,13和29,29是最大的一个。虽然我的代码可以工作,但即使对于小得多的输入,如6kk,答案也需要很长时间才能出现(大约需要15秒。对于12kk,需要37秒,所以增量甚至比线性更糟糕),这比我应该用作输入的数字小100k倍。下面是我的代码,任何关于提高代码效率的帮助都将非常感谢。
#include <stdio.h>
#include <math.h>
int main()
{
long long int number=600851475143;
int largest_prime_factor,i,j,k;
for (i=1;i<number/2;i+=2){
k=0;
j=3;
for (j=3;j<=sqrt(i);j+=2){
if (i%j==0){
k++;
break;
}
}
if (k==0){
if (number%i==0)
largest_prime_factor=i;
}
}
printf("The largest prime factor of 600851475143 is: %d",
largest_prime_factor);
return 0;
}
5条答案
按热度按时间hmtdttj41#
你应该把
sqrt(i)
移出for循环。它在每个循环中都计算。而且j*j <= i
比j <= sqrt(i)
快得多。您的代码中有错误:如果number是
long long int
,其他变量也应该是,否则条件i<number/2
总是为真!lsmd5eda2#
这段代码应该相当快,对于数字600851475143只需要几毫秒:
创建一个已经找到的素数列表可以加快对另一个可能因素的检查。
如果你找到了一个素数因子,你可以用这个素数因子除以你的数字,然后继续除法。也许这个除法需要多次进行。
number
中的最终值也是最大的素数因子。警告:我的代码根本没有经过测试。我只是确保结果对于
number = 600851475143ll
是正确的。而且我使用的是C++编译器,所以你可能需要做一些小的修改。对于更大的
number
,至少需要为primes
数组实现动态内存分配:c3frrgcw3#
使用j*j〈=i而不是j〈=sqrt(i),这取决于我使用的数字的大小,使代码快了5到10倍。而不是k++;也有轻微的影响。大约0.5%。我还没有检查所有内容。谢谢大家的宝贵意见!感谢他们,有很多东西值得思考和学习!
wqlqzqxt4#
你不需要遍历整个列表,一旦你找到一个素因子,你就用它分解你的数字,然后继续处理剩下的。
举个例子:600,851,475,143。你可以很快找到它的第一个素因子是71。如果你把600,851,475,143除以71,你会得到8,462,696,833。除了71之外,这两个数字都有相同的素因子。所以现在你可以搜索原始数字的最大因子,但搜索空间减少了2个数量级。
另外,请注意,如果数字本身是质数,代码将失败。
如果最后仍然是1,则返回数字本身。(您可以使用
number
进行初始化,但您很快就会明白我为什么选择1)因此,首先将2视为特殊情况:
然后在你的循环中做同样的事情,因为对于素数我们只需要检查它的平方根,我们将把我们的循环限制在两种情况下,这取决于我们是否仍然认为这个数可能是素数。
1.仍然是总理:测试到sqrt(数量)
1.不再Prime:测试直到最大因子超过剩余因子。
最后,修改后的代码可能看起来像这样:
还要注意,其他变量也应该是long long类型。
瓶颈是检查每个数是否是质数,如果质数因子本身很大,整个过程仍然会很慢。但是你可以得到一个更快的平均情况。对于你的例子,这个算法在不到一秒的时间内得到因子71,839,1471和6857。
up9lanfz5#
一般来说,没有有效的方法可以做到这一点:https://en.wikipedia.org/wiki/Integer_factorization#Difficulty_and_complexity
不过,还是有一些方法可以提高代码的速度。看看那篇文章中的一些算法吧。