简体   繁体   English

如何对大数进行素因数分解?

[英]How do I prime factorize large numbers?

I'm trying to solve Project Euler third question but while my code works perfectly with small numbers when I try to use big number it doesn't give me any answer.我正在尝试解决Project Euler 第三个问题,但是当我尝试使用大数字时,虽然我的代码可以完美地处理小数字,但它没有给我任何答案。

#include<iostream>

using std :: cout;
using std :: cin;
using std :: endl;

int main()
{
   long long int a = 0, bigPrime = 0, smallPrime = 2, prime = 0;
   cout << "Please enter a number...!" << endl;
   cin >> a;

   for(long long int i = 2 ; i < a ; i++)
   {
      for(long long int c = 2 ; c < i ; c++)
      {
         if(i % c != 0)
         {
            prime = i;
         }
         else
         {
            prime = 0;
            break;
         }
      }
      if(prime > 0 )
      {
         if(a % prime == 0)
         {
            bigPrime = prime;
         }
      }

  }


  cout << "The biggest prime is = " << bigPrime << endl;
  return 0;

} }

That's my bad code :) i am using ubuntu linux and g++ what is wrong with my code and how can i improve it?那是我的错误代码 :) 我正在使用 ubuntu linux 和 g++ 我的代码有什么问题,我该如何改进?

You can improve your program using one simple trick:您可以使用一个简单的技巧来改进您的程序:

Every time you find a divisor d , divide your number by d .每次找到除数d ,将您的数字除以d

That means that for every divisor found, your number gets smaller, making the remaining part easier to factor.这意味着对于找到的每个除数,您的数字会变小,从而使剩余部分更容易分解。

As a bonus, that means you don't need to be so careful about only using primes as divisors.作为奖励,这意味着您不需要非常小心地只使用素数作为除数。 Every time a divisor is found, it's the smallest divisor of the current number, and since it's the smallest divisor, it must be a prime.每次找到一个除数,它都是当前数的最小除数,因为它是最小的除数,所以它一定是素数。 That saves a whole level of looping.这节省了整个级别的循环。

The factors are extracted in order from smallest to highest, so in the end what you have is the highest prime factor - the answer to this challenge.这些因子是按从小到大的顺序提取的,所以最终你拥有的是最高的素因子——这个挑战的答案。

This is not a fast algorithm, but 600851475143 is not a large number and this algorithm will factor it no problem.这不是一个快速的算法,但 600851475143 不是一个很大的数字,这个算法将它分解没有问题。

For examle ( on ideone ):例如(在 ideone 上):

for (long long int d = 2; d * d <= a; d++) {
    if (a % d == 0) {
        a /= d;
        d--; // this is to handle repeated factors
    }
}

I also used the old d * d <= a trick but you don't even need it here.我还使用了旧的d * d <= a技巧,但您在这里甚至不需要它。 It helps if the highest factor is high, and in this example it is not.如果最高因子很高,这会有所帮助,而在本例中并非如此。

But the problem states that you just need to find the biggest prime of 600851475143, right?问题是你只需要找到 600851475143 的最大质数,对吗? Why don't you just iterate from sqrt(600851475143) to 2 and return the first number that is a prime?为什么不直接从 sqrt(600851475143) 迭代到 2 并返回第一个质数?

bool isPrime(uint64_t num)
{
  bool result = true;
  for(uint64_t i = 2; i < std::sqrt(num); ++i)
  {
    if(num % i == 0)
    {
      result = false;
      break;
    }
  }
  return result;
}

int main()
{
  uint64_t num = 600851475143;
  uint64_t i = std::sqrt(num);
  while (i > 1)
  {
    i--;
    if (num%i != 0) continue;
    if (isPrime(i))
    {
      break;
    }
  }
  std::cout << i << std::endl;
  return 0;
}

For sure it can be done faster, but it takes 10ms on my machine, so I guess it's not terrible.当然它可以做得更快,但在我的机器上需要 10 毫秒,所以我想这并不可怕。

#include <iostream>

using namespace std;

typedef long long ulong;

int main()
{
ulong num = 600851475143;
ulong div = num;
ulong p = 0;

ulong i = 2;
while (i * i <= div)
{
    if (div % i == 0)
    {
        div /= i;
        p = i;
    }
    else {
        i++;
    }
}

if (div > p) 
{ 
    p = div;
}

cout << p << endl;

return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM