我正在尝试通过Project Euler工作,我在问题03上遇到障碍。我有一个适用于较小数字的算法,但问题3使用非常非常大的数字。
问题03: 13195的主要因素是5,7,13和29。 600851475143的最大主要因素是什么?
这是我在C#中的解决方案,它一直在运行,我认为接近一个小时。我不是在寻找答案,因为我确实想自己解决这个问题。主要是寻求一些帮助。
static void Main(string[] args) {
const long n = 600851475143;
//const long n = 13195;
long count, half, largestPrime = 0;
bool IsAPrime;
half = n / 2;
for (long i = half; i > 1 && largestPrime == 0; i--) {
if (n % i == 0) { // these are factors of n
count = 1;
IsAPrime = true;
while (++count < i && IsAPrime) {
if (i % count == 0) { // does a factor of n have a factor? (not prime)
IsAPrime = false;
}
}
if (IsAPrime) {
largestPrime = i;
}
}
}
Console.WriteLine("The largest prime factor is " + largestPrime.ToString() + ".");
Console.ReadLine();
}
答案 0 :(得分:14)
对于初学者而言,不是在n / 2开始搜索,而是在n的平方根处开始。你会得到一半的因素,另一半是他们的补充。
例如:
n = 27
start at floor(sqrt(27)) = 5
is 5 a factor? no
is 4 a factor? no
is 3 a factor? yes. 27 / 3 = 9. 9 is also a factor.
is 2 a factor? no.
factors are 3 and 9.
答案 1 :(得分:11)
long n = 600851475143L; //not even, so 2 wont be a factor
int factor = 3;
while( n > 1)
{
if(n % factor == 0)
{
n/=factor;
}else
factor += 2; //skip even numbrs
}
print factor;
这应该足够快......注意,没有必要检查素数......
答案 2 :(得分:10)
虽然这个问题要求最大素因子,但这并不一定意味着你必须先找到那个......
答案 3 :(得分:10)
实际上,对于这种情况,您不需要检查素性,只需删除您找到的因子。从n == 2开始向上扫描。当邪恶的大数字%n == 0时,将邪恶的大数字除以n并继续使用较小的邪恶数字。当n> = = sqrt(big-evil-number)时停止。
任何现代机器都不应超过几秒钟。
答案 4 :(得分:6)
您需要减少正在进行的检查量...想一想您需要测试的数字。
为了更好的方法,请阅读Sieve of Erathosthenes ...它应该让你指向正确的方向。
答案 5 :(得分:3)
至于接受nicf答案的理由:
对于Euler的问题是可以的,但是在一般情况下不能使它成为有效的解决方案。为什么你会尝试偶数数字?
这会导致一些代码如下:
n = abs(number);
result = 1;
if (n mod 2 = 0) {
result = 2;
while (n mod 2 = 0) n /= 2;
}
for(i=3; i<sqrt(n); i+=2) {
if (n mod i = 0) {
result = i;
while (n mod i = 0) n /= i;
}
}
return max(n,result)
有一些模数测试是超级的,因为如果所有因子2和3都已被删除,则n永远不会被除以6。你只能允许我的素数。
就像一个例子,让我们看一下21的结果:
21不是偶数,所以我们进入for循环,上限sqrt(21)(~4.6)。 然后我们可以将21除以3,因此结果= 3且n = 21/3 = 7.我们现在只需要测试到sqrt(7)。它小于3,所以我们完成了for循环。我们返回n和结果的最大值,即n = 7.
答案 6 :(得分:2)
我这样做的方法是搜索素数(p
),从2开始使用Eratosthenes筛选。该算法可以在速度相当快的机器上找到1000万以下<2s以下的所有素数。
对于您找到的每个素数,测试将其划分为您正在测试的数字,直到您不能再进行整数除法。 (即检查n % p == 0
如果为真,则除以。)
一旦n = 1
,你就完成了。成功分割的n
的最后一个值是您的答案。在旁注中,您还发现了n
的所有主要因素。
PS:如前所述,您只需要在2 <= n <= sqrt(p)
之间搜索素数。这使得Eratosthenes的Sieve成为一种非常快速且易于实现的算法。
答案 7 :(得分:2)
找到答案后,在浏览器中输入以下内容;)
http://www.wolframalpha.com/input/?i=FactorInteger(600851475143)
Wofram Alpha是你的朋友
答案 8 :(得分:1)
在Java中使用递归算法运行不到一秒......想想你的算法,因为它包含了一些可以消除的“暴力破解”。另请参阅如何通过中间计算减少您的解决方案空间。
答案 9 :(得分:1)
C ++中的轻松:
#include <iostream>
using namespace std;
int main()
{
unsigned long long int largefactor = 600851475143;
for(int i = 2;;)
{
if (largefactor <= i)
break;
if (largefactor % i == 0)
{
largefactor = largefactor / i;
}
else
i++;
}
cout << largefactor << endl;
cin.get();
return 0;
}
答案 10 :(得分:1)
这个C ++解决方案在我的英特尔四核i5 iMac(3.1 GHz)上耗时3.7毫秒
#include <iostream>
#include <cmath>
#include <ctime>
using std::sqrt; using std::cin;
using std::cout; using std::endl;
long lpf(long n)
{
long start = (sqrt(n) + 2 % 2);
if(start % 2 == 0) start++;
for(long i = start; i != 2; i -= 2)
{
if(n % i == 0) //then i is a factor of n
{
long j = 2L;
do {
++j;
}
while(i % j != 0 && j <= i);
if(j == i) //then i is a prime number
return i;
}
}
}
int main()
{
long n, ans;
cout << "Please enter your number: ";
cin >> n; //600851475143L
time_t start, end;
time(&start);
int i;
for(i = 0; i != 3000; ++i)
ans = lpf(n);
time(&end);
cout << "The largest prime factor of your number is: " << ans << endl;
cout << "Running time: " << 1000*difftime(end, start)/i << " ms." << endl;
return 0;
}
答案 11 :(得分:0)
所有项目欧拉的问题应该花费不到一分钟;即使Python中未经优化的递归实现也需要不到一秒[0.09秒(cpu 4.3GHz)]。
from math import sqrt
def largest_primefactor(number):
for divisor in range(2, int(sqrt(number) + 1.5)): # divisor <= sqrt(n)
q, r = divmod(number, divisor)
if r == 0:
#assert(isprime(divisor))
# recursion depth == number of prime factors,
# e.g. 4 has two prime factors: {2,2}
return largest_primefactor(q)
return number # number is a prime itself
答案 12 :(得分:0)
我喜欢lill mud的解决方案:
要求“mathn.rb”
put 600851475143.prime_division.last.first
我检查了here
答案 13 :(得分:0)
也许它被认为是作弊,但是haskell的一种可能性就是写(为了记录我自己编写了这些行并且没有检查过eulerproject线程);
<customConfig>
<config key="convert_urls">false</config>
...
</customConfig>
答案 14 :(得分:-1)
尝试使用Miller-Rabin Primality Test来测试一个素数的数字。这应该会大大加快速度。
答案 15 :(得分:-1)
另一种方法是首先将所有素数提高到n / 2,然后检查模数是否为0。 我可以找到一个用于获取 n 所有素数的算法here。