项目欧拉问题3帮助

时间:2008-10-14 14:26:06

标签: c# algorithm language-agnostic primes

我正在尝试通过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();
    }

16 个答案:

答案 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是偶数,则向左移动(除以 2)直到它不再存在。如果是 那么,2是最大的素数 因素。
  • 如果n不均匀,则不必 测试偶数。
  • 你可以停下来 SQRT(N)。
  • 你只需要测试素数 因素。测试可能会更快 是否k除以n然后测试它 虽然是为了素性。
  • 您可以优化上限 当你找到一个因素时会飞。

这会导致一些代码如下:

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)

找到答案后,在浏览器中输入以下内容;)

http://www.wolframalpha.com/input/?i=FactorInteger(600851475143)

Wofram Alpha是你的朋友

答案 7 :(得分:2)

我这样做的方法是搜索素数(p),从2开始使用Eratosthenes筛选。该算法可以在速度相当快的机器上找到1000万以下<2s以下的所有素数。

对于您找到的每个素数,测试将其划分为您正在测试的数字,直到您不能再进行整数除法。 (即检查n % p == 0如果为真,则除以。)

一旦n = 1,你就完成了。成功分割的n的最后一个值是您的答案。在旁注中,您还发现了n的所有主要因素。

PS:如前所述,您只需要在2 <= n <= sqrt(p)之间搜索素数。这使得Eratosthenes的Sieve成为一种非常快速且易于实现的算法。

答案 8 :(得分: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;
}

答案 9 :(得分: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;
}

答案 10 :(得分:1)

在Java中使用递归算法运行不到一秒......想想你的算法,因为它包含了一些可以消除的“暴力破解”。另请参阅如何通过中间计算减少您的解决方案空间。

答案 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)

你可能想看到这个: Is there a simple algorithm that can determine if X is prime, and not confuse a mere mortal programmer?

我喜欢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)

另一种方法是首先将所有素数提高到n / 2,然后检查模数是否为0。 我可以找到一个用于获取 n 所有素数的算法here

答案 15 :(得分:-1)

尝试使用Miller-Rabin Primality Test来测试一个素数的数字。这应该会大大加快速度。