Thuật toán tìm hệ số nguyên tố lớn nhất của một số


183

Cách tiếp cận tốt nhất để tính hệ số nguyên tố lớn nhất của một số là gì?

Tôi nghĩ rằng hiệu quả nhất sẽ là như sau:

  1. Tìm số nguyên tố thấp nhất phân chia sạch
  2. Kiểm tra xem kết quả của phép chia là số nguyên tố
  3. Nếu không, tìm mức thấp nhất tiếp theo
  4. Chuyển đến 2.

Tôi dựa trên giả định này để dễ dàng tính toán các thừa số nguyên tố nhỏ. Đây có phải là về phải không? Những cách tiếp cận khác tôi nên xem xét?

Chỉnh sửa: Bây giờ tôi đã nhận ra rằng cách tiếp cận của tôi là vô ích nếu có nhiều hơn 2 yếu tố chính, vì bước 2 thất bại khi kết quả là sản phẩm của hai số nguyên tố khác, do đó cần có thuật toán đệ quy.

Chỉnh sửa lại: Và bây giờ tôi đã nhận ra rằng điều này vẫn hoạt động, bởi vì số nguyên tố tìm thấy cuối cùng phải là số cao nhất, do đó, bất kỳ thử nghiệm nào nữa về kết quả không chính từ bước 2 sẽ dẫn đến một số nguyên tố nhỏ hơn.


Cách tiếp cận của tôi là: (1) chia số lớn, số có thể cho 2; (2) kiểm tra xem số lượng lớn có chia đều cho nó không; (3) nếu vậy, kiểm tra xem số chia cho 2 số có phải là số nguyên tố không. Nếu có, trả lại nó. (4) Khác, trừ 1 từ chia cho 2 số, quay lại bước 3.
Kevin Meredith

1.tìm bất kỳ số nào phân chia rõ ràng (cho i = 2 đến int (sqr (num))) 2.chia cho số đó (num = num / i) và lặp lại cho đến khi không tìm thấy gì trong khoảng num1. hệ số lớn nhất3.
user3819867

1
Chúng ta có thể phân chia với các số nguyên tố nhỏ, và số cuối cùng còn lại, là Hệ số nguyên tố lớn nhất (tôi đoán)

Câu trả lời:


134

Trên thực tế, có một số cách hiệu quả hơn để tìm các yếu tố của số lượng lớn (đối với các phân chia thử nghiệm nhỏ hơn hoạt động hợp lý).

Một phương pháp rất nhanh nếu số đầu vào có hai yếu tố rất gần với căn bậc hai của nó được gọi là hệ số Fermat . Nó sử dụng danh tính N = (a + b) (a - b) = a ^ 2 - b ^ 2 và rất dễ hiểu và thực hiện. Thật không may, nói chung nó không nhanh lắm.

Phương pháp được biết đến nhiều nhất để bao thanh toán các số dài tới 100 chữ số là rây Quadratic . Là một phần thưởng, một phần của thuật toán được thực hiện dễ dàng với xử lý song song.

Một thuật toán khác mà tôi đã nghe nói là thuật toán Rho của Pollard . Nó không hiệu quả như Quadratic Sàng nói chung nhưng dường như dễ thực hiện hơn.


Khi bạn đã quyết định cách chia một số thành hai yếu tố, đây là thuật toán nhanh nhất tôi có thể nghĩ ra để tìm ra thừa số nguyên tố lớn nhất của một số:

Tạo một hàng đợi ưu tiên mà ban đầu lưu trữ số đó. Mỗi lần lặp, bạn loại bỏ số cao nhất khỏi hàng đợi và cố gắng chia nó thành hai yếu tố (tất nhiên không cho phép 1 là một trong những yếu tố đó). Nếu bước này không thành công, số là số nguyên tố và bạn có câu trả lời của mình! Nếu không, bạn thêm hai yếu tố vào hàng đợi và lặp lại.


3
Pollard rho và phương pháp đường cong elip tốt hơn nhiều trong việc loại bỏ các thừa số nguyên tố nhỏ của số của bạn so với sàng bậc hai. QS có cùng thời gian chạy bất kể số lượng. Cách tiếp cận nào nhanh hơn phụ thuộc vào số của bạn là gì; QS sẽ bẻ khóa các số yếu tố nhanh hơn trong khi rho và ECM sẽ bẻ khóa các số dễ yếu tố nhanh hơn.
tmyklebu

Cảm ơn bạn đã đề xuất biến thể Quadratic. Tôi cần phải thực hiện điều này cho một trong những khách hàng của mình, phiên bản ban đầu tôi nghĩ ra là một cái gì đó dọc theo dòng của những gì @mercutio gợi ý trong câu hỏi của anh ấy. Giải pháp bậc hai là những gì đang cung cấp năng lượng cho công cụ của khách hàng của tôi tại math.tools/calculator/prime-factors .
dors

Nếu có một cách hiệu quả để giải quyết vấn đề này, điều đó không có nghĩa là mã hóa web không an toàn?
BKSpurgeon

141

Đây là thuật toán tốt nhất mà tôi biết (bằng Python)

def prime_factors(n):
    """Returns all the prime factors of a positive integer"""
    factors = []
    d = 2
    while n > 1:
        while n % d == 0:
            factors.append(d)
            n /= d
        d = d + 1

    return factors


pfs = prime_factors(1000)
largest_prime_factor = max(pfs) # The largest element in the prime factor list

Phương pháp trên chạy trong O(n) trường hợp xấu nhất (khi đầu vào là số nguyên tố).

EDIT:
Dưới đây là O(sqrt(n))phiên bản, như được đề xuất trong bình luận. Đây là mã, một lần nữa.

def prime_factors(n):
    """Returns all the prime factors of a positive integer"""
    factors = []
    d = 2
    while n > 1:
        while n % d == 0:
            factors.append(d)
            n /= d
        d = d + 1
        if d*d > n:
            if n > 1: factors.append(n)
            break
    return factors


pfs = prime_factors(1000)
largest_prime_factor = max(pfs) # The largest element in the prime factor list

11
Vui lòng đọc và / hoặc chạy mã này trước khi bỏ phiếu. Nó hoạt động tốt. Chỉ cần sao chép và dán. Khi viết Prime_factors (1000) sẽ trả về [2,2,2,5,5,5], nên được hiểu là 2 ^ 3 * 5 ^ 3, hay còn gọi là thừa số nguyên tố.
Triptych

11
"chạy trong O(sqrt(n))trường hợp xấu nhất" - Không, nó chạy trong O(n)trường hợp xấu nhất (ví dụ khi nào nlà số nguyên tố.)
Sheldon L. Cooper

16
Dễ dàng biến nó thành O (sqrt (n)), bạn chỉ cần dừng vòng lặp khi d * d> n và nếu n> 1 tại thời điểm này thì giá trị của nó sẽ được thêm vào danh sách các thừa số nguyên tố.
Sumudu Fernando

5
có phải có một cái tên cho thứ này?
Forethinker

11
vì 2 là số nguyên tố chẵn duy nhất, vì vậy thay vì thêm 1 mỗi lần, bạn có thể lặp riêng cho d = 2 và sau đó tăng nó lên 1 và sau đó từ d = 3 trở đi, bạn có thể tăng thêm 2. vì vậy nó sẽ giảm số lặp đi lặp lại ... :)
tailor_raj

18

Câu trả lời của tôi dựa trên Triptych , nhưng cải thiện rất nhiều về nó. Nó dựa trên thực tế là ngoài 2 và 3, tất cả các số nguyên tố có dạng 6n-1 hoặc 6n + 1.

var largestPrimeFactor;
if(n mod 2 == 0)
{
    largestPrimeFactor = 2;
    n = n / 2 while(n mod 2 == 0);
}
if(n mod 3 == 0)
{
    largestPrimeFactor = 3;
    n = n / 3 while(n mod 3 == 0);
}

multOfSix = 6;
while(multOfSix - 1 <= n)
{
    if(n mod (multOfSix - 1) == 0)
    {
        largestPrimeFactor = multOfSix - 1;
        n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
    }

    if(n mod (multOfSix + 1) == 0)
    {
        largestPrimeFactor = multOfSix + 1;
        n = n / largestPrimeFactor while(n mod largestPrimeFactor == 0);
    }
    multOfSix += 6;
}

Gần đây tôi đã viết một bài viết trên blog giải thích cách thức hoạt động của thuật toán này.

Tôi sẽ mạo hiểm rằng một phương pháp không cần thử nghiệm tính nguyên thủy (và không có cấu trúc sàng) sẽ chạy nhanh hơn phương pháp sử dụng phương pháp đó. Nếu đó là trường hợp, đây có lẽ là thuật toán nhanh nhất ở đây.


12
Bạn thực sự có thể đưa ý tưởng này đi xa hơn, ví dụ: ngoài 2,3,5 tất cả các số nguyên tố có dạng 30n + k (n> = 0) trong đó k chỉ lấy các giá trị đó trong khoảng từ 1 đến 29 không chia hết cho 2,3 hoặc 5, tức là 7,11,13,17,19,23,29. Bạn thậm chí có thể có khả năng thích ứng linh hoạt này sau mỗi vài số nguyên tố bạn tìm thấy cho đến 2 * 3 * 5 * 7 * ... * n + k trong đó k không được chia hết cho bất kỳ số nguyên tố nào trong số này (lưu ý rằng không phải tất cả các số nguyên tố k đều có thể cần là số nguyên tố, ví dụ: với 210n + k bạn phải bao gồm 121, nếu không bạn sẽ bỏ lỡ 331 )
Tobias Kienzler

2
Tôi đoán nó nên như vậywhile (multOfSix - 1 <= n)
Nader Ghanbari

8

Mã JavaScript:

'option strict';

function largestPrimeFactor(val, divisor = 2) { 
    let square = (val) => Math.pow(val, 2);

    while ((val % divisor) != 0 && square(divisor) <= val) {
        divisor++;
    }

    return square(divisor) <= val
        ? largestPrimeFactor(val / divisor, divisor)
        : val;
}

Ví dụ sử dụng:

let result = largestPrimeFactor(600851475143);

Đây là một ví dụ về mã :


7

Tương tự như câu trả lời @Triptych nhưng cũng khác. Trong ví dụ này danh sách hoặc từ điển không được sử dụng. Mã được viết bằng Ruby

def largest_prime_factor(number)
  i = 2
  while number > 1
    if number % i == 0
      number /= i;
    else
      i += 1
    end
  end
  return i
end

largest_prime_factor(600851475143)
# => 6857

Cuối cùng, một cái gì đó có thể đọc được và ngay lập tức (trong js) có thể thực thi cùng một lúc. Tôi đã cố gắng sử dụng danh sách nguyên tố vô hạn và nó đã quá chậm trên 1 triệu.
Ebuall

4

Tất cả các số có thể được biểu thị dưới dạng tích của số nguyên tố, ví dụ:

102 = 2 x 3 x 17
712 = 2 x 2 x 2 x 89

Bạn có thể tìm thấy những thứ này bằng cách bắt đầu từ 2 và chỉ cần tiếp tục chia cho đến khi kết quả không phải là bội số của bạn:

712 / 2 = 356 .. 356 / 2 = 178 .. 178 / 2 = 89 .. 89 / 89 = 1

sử dụng phương pháp này, bạn không thực sự phải tính toán bất kỳ số nguyên tố nào: tất cả chúng đều là số nguyên tố, dựa trên thực tế là bạn đã tính đến số càng nhiều càng tốt với tất cả các số trước đó.

number = 712;
currNum = number;    // the value we'll actually be working with
for (currFactor in 2 .. number) {
    while (currNum % currFactor == 0) {
        // keep on dividing by this number until we can divide no more!
        currNum = currNum / currFactor     // reduce the currNum
    }
    if (currNum == 1) return currFactor;    // once it hits 1, we're done.
}

Có, nhưng điều này là không hiệu quả khủng khiếp. Khi bạn đã chia hết 2 giây, bạn thực sự không nên thử chia cho 4 hoặc 6 hoặc ...; Nó thực sự hiệu quả hơn nhiều trong giới hạn chỉ kiểm tra các số nguyên tố, hoặc sử dụng một số thuật toán toher.
wnoise

6
+1 để bù đắp wnoise, người mà tôi nghĩ là sai. Cố gắng chia cho 4 sẽ chỉ xảy ra một lần, và sẽ thất bại ngay lập tức. Tôi không nghĩ điều đó tệ hơn việc loại bỏ 4 khỏi danh sách một số ứng cử viên, và nó chắc chắn nhanh hơn việc tìm thấy tất cả các số nguyên tố trước đó.
Triptych

2
@Beowulf. Hãy thử chạy mã này trước khi bỏ phiếu xuống. Nó trả về các thừa số nguyên tố; bạn không hiểu thuật toán.
Triptych

3
mã hoạt động tốt, nhưng chậm nếu số đến là số nguyên tố. Tôi cũng sẽ chỉ chạy lên đến hình vuông và tăng thêm 2. Tuy nhiên, nó có thể quá chậm đối với những con số rất lớn.
blabla999

4
Blabla999 là hoàn toàn chính xác. Ví dụ là 1234567898766700 = 2 * 2 * 5 * 5 * 12345678987667. Khi chúng tôi đạt được currFactor = 3513642, chúng tôi biết rằng 12345678987667 là số nguyên tố và sẽ trả lại nó làm câu trả lời. Thay vào đó, mã này sẽ tiếp tục liệt kê cho đến khi 12345678987667. Đó là chậm hơn 3.513.642x so với cần thiết.
Will Ness

4
    //this method skips unnecessary trial divisions and makes 
    //trial division more feasible for finding large primes

    public static void main(String[] args) 
    {
        long n= 1000000000039L; //this is a large prime number 
        long i = 2L;
        int test = 0;

        while (n > 1)
        {
            while (n % i == 0)
            {
                n /= i;     
            }

            i++;

            if(i*i > n && n > 1) 
            {
                System.out.println(n); //prints n if it's prime
                test = 1;
                break;
            }
        }

        if (test == 0)  
            System.out.println(i-1); //prints n if it's the largest prime factor
    }

1
Bạn đã thử mã của mình với 1.000.000.000.039 chưa? nó cũng nên chạy trong nháy mắt Phải không?
Will Ness

2
Bạn có thể biết trước mà không cần cố gắng. 10 ^ 12 = (2 * 5) ^ 12 = 2 ^ 12 * 5 ^ 12. Vì vậy, whilevòng lặp của bạn sẽ đi qua icác giá trị của 2,2,2,2,2,2,2,2,2,2,2,2, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5, 2,3,4,5. Tất cả 60 lần lặp. Nhưng với (10 ^ 12 + 39) sẽ có (10 ^ 12 + 38) lần lặp , i=2,3,4,5,6,...,10^12+39. Ngay cả khi 10 ^ 10 op mất một giây, 10 ^ 12 sẽ mất 100 giây. Nhưng chỉ cần 10 ^ 6 lần lặp là thực sự cần thiết và nếu 10 ^ 10 op mất một giây, 10 ^ 6 sẽ mất 1 / 10.000 của một giây.
Will Ness

1
Bởi vì tôi đã không nhận ra (10 ^ 12 + 39) là số nguyên tố mà tôi làm bây giờ. Tôi hiểu chính xác những gì bạn đang nói.
the_prole

1
OK, vì vậy bạn có thể thay đổi mã của mình để không có sự chậm chạp lớn như vậy đối với các số nguyên tố: if n = a b và a <= b, thì a a <= b a = n, tức là a a <= n . Và nếu chúng ta đạt được +1, thì n chắc chắn là số nguyên tố. (ping tôi nếu bạn chỉnh sửa câu trả lời của mình để kết hợp điều này).
Will Ness

1
chuyện gì xảy ra khi long n = 2*1000000000039Lnào Nó hoạt động nhanh như nó cần? (ngoài ra, bạn có thể đơn giản hóa mã của mình bằng cách sử dụng một return;câu lệnh không?). (nếu bạn muốn tôi ngừng huých bạn, chỉ cần nói như vậy;))
Will Ness

4

Giải pháp đơn giản nhất là một cặp hàm đệ quy lẫn nhau .

Hàm đầu tiên tạo ra tất cả các số nguyên tố:

  1. Bắt đầu với một danh sách tất cả các số tự nhiên lớn hơn 1.
  2. Xóa tất cả các số không phải là số nguyên tố. Đó là, những con số không có yếu tố chính (ngoài bản thân chúng). Xem bên dưới.

Hàm thứ hai trả về các thừa số nguyên tố của một số đã cho ntheo thứ tự tăng dần.

  1. Lấy một danh sách của tất cả các số nguyên tố (xem ở trên).
  2. Xóa tất cả các số không phải là yếu tố của n.

Hệ số nguyên tố lớn nhất nlà số cuối cùng được cho bởi hàm thứ hai.

Thuật toán này yêu cầu một danh sách lười biếng hoặc một ngôn ngữ (hoặc cấu trúc dữ liệu) với nhu cầu gọi ngữ nghĩa theo yêu .

Để làm rõ, đây là một triển khai (không hiệu quả) ở trên trong Haskell:

import Control.Monad

-- All the primes
primes = 2 : filter (ap (<=) (head . primeFactors)) [3,5..]

-- Gives the prime factors of its argument
primeFactors = factor primes
  where factor [] n = []
        factor xs@(p:ps) n =
          if p*p > n then [n]
          else let (d,r) = divMod n p in
            if r == 0 then p : factor xs d
            else factor ps n

-- Gives the largest prime factor of its argument
largestFactor = last . primeFactors

Làm cho điều này nhanh hơn chỉ là vấn đề thông minh hơn trong việc phát hiện các số nào là số nguyên tố và / hoặc các yếu tố của n, nhưng thuật toán vẫn giữ nguyên.


2
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)

Có một số thử nghiệm modulo là không cần thiết, vì n không bao giờ có thể chia cho 6 nếu tất cả các yếu tố 2 và 3 đã bị loại bỏ. Bạn chỉ có thể cho phép các số nguyên tố cho i, được hiển thị trong một số câu trả lời khác ở đây.

Bạn thực sự có thể đan xen sàng của Eratosthenes ở đây:

  • Đầu tiên tạo danh sách các số nguyên lên đến sqrt (n).
  • Trong vòng lặp for, tất cả các bội số của i cho đến sqrt (n) mới là không phải là số nguyên tố và thay vào đó sử dụng vòng lặp while.
  • đặt i thành số nguyên tố tiếp theo trong danh sách.

Cũng xem câu hỏi này .


2

Tôi biết đây không phải là một giải pháp nhanh. Gửi bài như hy vọng dễ hiểu hơn giải pháp chậm.

 public static long largestPrimeFactor(long n) {

        // largest composite factor must be smaller than sqrt
        long sqrt = (long)Math.ceil(Math.sqrt((double)n));

        long largest = -1;

        for(long i = 2; i <= sqrt; i++) {
            if(n % i == 0) {
                long test = largestPrimeFactor(n/i);
                if(test > largest) {
                    largest = test;
                }
            }
        }

        if(largest != -1) {
            return largest;
        }

        // number is prime
        return n;
    } 

1

Phương pháp lặp Python bằng cách loại bỏ tất cả các thừa số nguyên tố khỏi số

def primef(n):
    if n <= 3:
        return n
    if n % 2 == 0:
        return primef(n/2)
    elif n % 3 ==0:
        return primef(n/3)
    else:
        for i in range(5, int((n)**0.5) + 1, 6):
            #print i
            if n % i == 0:
                return primef(n/i)
            if n % (i + 2) == 0:
                return primef(n/(i+2))
    return n

1

Tôi đang sử dụng thuật toán tiếp tục chia số cho Prime Factor hiện tại.

Giải pháp của tôi trong python 3:

def PrimeFactor(n):
    m = n
    while n%2==0:
        n = n//2
    if n == 1:         # check if only 2 is largest Prime Factor 
        return 2
    i = 3
    sqrt = int(m**(0.5))  # loop till square root of number
    last = 0              # to store last prime Factor i.e. Largest Prime Factor
    while i <= sqrt :
        while n%i == 0:
            n = n//i       # reduce the number by dividing it by it's Prime Factor
            last = i
        i+=2
    if n> last:            # the remaining number(n) is also Factor of number 
        return n
    else:
        return last
print(PrimeFactor(int(input()))) 

Đầu vào: 10 Đầu ra:5

Đầu vào: 600851475143 Đầu ra:6857


0

Đây là nỗ lực của tôi trong c #. Bản in cuối cùng là yếu tố chính lớn nhất của số. Tôi đã kiểm tra và nó hoạt động.

namespace Problem_Prime
{
  class Program
  {
    static void Main(string[] args)
    {
      /*
       The prime factors of 13195 are 5, 7, 13 and 29.

      What is the largest prime factor of the number 600851475143 ?
       */
      long x = 600851475143;
      long y = 2;
      while (y < x)
      {
        if (x % y == 0)
        {
          // y is a factor of x, but is it prime
          if (IsPrime(y))
          {
            Console.WriteLine(y);
          }
          x /= y;
        }

        y++;

      }
      Console.WriteLine(y);
      Console.ReadLine();
    }
    static bool IsPrime(long number)
    {
      //check for evenness
      if (number % 2 == 0)
      {
        if (number == 2)
        {
          return true;
        }
        return false;
      }
      //don't need to check past the square root
      long max = (long)Math.Sqrt(number);
      for (int i = 3; i <= max; i += 2)
      {
        if ((number % i) == 0)
        {
          return false;
        }
      }
      return true;
    }

  }
}

0
#python implementation
import math
n = 600851475143
i = 2
factors=set([])
while i<math.sqrt(n):
   while n%i==0:
       n=n/i
       factors.add(i)
   i+=1
factors.add(n)
largest=max(factors)
print factors
print largest

1
25 là yếu tố chính lớn nhất của 25?
Will Ness

0

Tính hệ số nguyên tố lớn nhất của một số bằng cách sử dụng đệ quy trong C ++. Hoạt động của mã được giải thích dưới đây:

int getLargestPrime(int number) {
    int factor = number; // assumes that the largest prime factor is the number itself
    for (int i = 2; (i*i) <= number; i++) { // iterates to the square root of the number till it finds the first(smallest) factor
        if (number % i == 0) { // checks if the current number(i) is a factor
            factor = max(i, number / i); // stores the larger number among the factors
            break; // breaks the loop on when a factor is found
        }
    }
    if (factor == number) // base case of recursion
        return number;
    return getLargestPrime(factor); // recursively calls itself
}

0

Dưới đây là cách tiếp cận của tôi để nhanh chóng tính toán yếu tố nguyên tố lớn nhất. Nó dựa trên thực tế rằng sửa đổi xkhông chứa các yếu tố không chính. Để đạt được điều đó, chúng tôi chia xngay khi một yếu tố được tìm thấy. Sau đó, điều duy nhất còn lại là trả lại yếu tố lớn nhất. Nó sẽ là nguyên tố.

Mã (Haskell):

f max' x i | i > x = max'
           | x `rem` i == 0 = f i (x `div` i) i  -- Divide x by its factor
           | otherwise = f max' x (i + 1)  -- Check for the next possible factor

g x = f 2 x 2

Nhưng điều này sẽ không cố gắng phân chia với tất cả các số chẵn?
Janus Troelsen

0

Thuật toán C ++ sau đây không phải là thuật toán tốt nhất, nhưng nó hoạt động với số lượng dưới một tỷ và khá nhanh

#include <iostream>
using namespace std;

// ------ is_prime ------
// Determines if the integer accepted is prime or not
bool is_prime(int n){
    int i,count=0;
    if(n==1 || n==2)
      return true;
    if(n%2==0)
      return false;
    for(i=1;i<=n;i++){
    if(n%i==0)
        count++;
    }
    if(count==2)
      return true;
    else
      return false;
 }
 // ------ nextPrime -------
 // Finds and returns the next prime number
 int nextPrime(int prime){
     bool a = false;
     while (a == false){
         prime++;
         if (is_prime(prime))
            a = true;
     }
  return prime;
 }
 // ----- M A I N ------
 int main(){

      int value = 13195;
      int prime = 2;
      bool done = false;

      while (done == false){
          if (value%prime == 0){
             value = value/prime;
             if (is_prime(value)){
                 done = true;
             }
          } else {
             prime = nextPrime(prime);
          }
      }
        cout << "Largest prime factor: " << value << endl;
 }

0

Tìm thấy giải pháp này trên web bởi "James Wang"

public static int getLargestPrime( int number) {

    if (number <= 1) return -1;

    for (int i = number - 1; i > 1; i--) {
        if (number % i == 0) {
            number = i;
        }
    }
    return number;
}

0

Yếu tố chính sử dụng sàng:

#include <bits/stdc++.h>
using namespace std;
#define N 10001  
typedef long long ll;
bool visit[N];
vector<int> prime;

void sieve()
{
            memset( visit , 0 , sizeof(visit));
            for( int i=2;i<N;i++ )
            {
                if( visit[i] == 0)
                {
                    prime.push_back(i);
                    for( int j=i*2; j<N; j=j+i )
                    {
                        visit[j] = 1;
                    }
                }
            }   
}
void sol(long long n, vector<int>&prime)
{
            ll ans = n;
            for(int i=0; i<prime.size() || prime[i]>n; i++)
            {
                while(n%prime[i]==0)
                {
                    n=n/prime[i];
                    ans = prime[i];
                }
            }
            ans = max(ans, n);
            cout<<ans<<endl;
}
int main() 
{
           ll tc, n;
           sieve();

           cin>>n;
           sol(n, prime);

           return 0;
}

-1

Dường như với tôi, bước # 2 của thuật toán được đưa ra sẽ không phải là một cách tiếp cận hiệu quả. Bạn không có kỳ vọng hợp lý rằng nó là nguyên tố.

Ngoài ra, câu trả lời trước đây cho thấy Sàng của Eratosthenes là hoàn toàn sai. Tôi vừa viết hai chương trình cho nhân tố 123456789. Một chương trình dựa trên Sàng, một chương trình dựa trên:

1)  Test = 2 
2)  Current = Number to test 
3)  If Current Mod Test = 0 then  
3a)     Current = Current Div Test 
3b)     Largest = Test
3c)     Goto 3. 
4)  Inc(Test) 
5)  If Current < Test goto 4
6)  Return Largest

Phiên bản này nhanh hơn 90 lần so với Sàng.

Vấn đề là, trên các bộ xử lý hiện đại, loại hoạt động quan trọng hơn rất nhiều so với số lượng hoạt động, chưa kể thuật toán ở trên có thể chạy trong bộ đệm, Sàng không thể. Sàng sử dụng rất nhiều thao tác nổi bật trong tất cả các số tổng hợp.

Ngoài ra, cũng lưu ý rằng các yếu tố phân chia của tôi khi chúng được xác định sẽ làm giảm không gian phải được kiểm tra.


đó là những gì tôi đã nói, nhưng đã bỏ phiếu :( Tôi đoán vấn đề là nếu số đó có thừa số nguyên tố thực sự lớn (chẳng hạn như chính nó), thì phương pháp này phải lặp lại theo con số đó mặc dù vậy, phương pháp này khá hiệu quả.
nickf

Đọc lại thông qua bạn cũng vậy nhưng phần đầu tiên của bạn thật khó hiểu.
Loren Pechtel

Hãy thử số này 143816789988504044536402352738195137863656439, cho tôi biết hiệu quả của việc này như thế nào ...
MichaelICE

-1

Trước tiên, tính toán một danh sách lưu các số nguyên tố, ví dụ 2 3 5 7 11 13 ...

Mỗi khi bạn xác định số nguyên tố, hãy sử dụng triển khai bằng Triptych nhưng lặp lại danh sách các số nguyên tố này thay vì số nguyên tự nhiên.


-1

Với Java:

Đối với intcác giá trị:

public static int[] primeFactors(int value) {
    int[] a = new int[31];
    int i = 0, j;
    int num = value;
    while (num % 2 == 0) {
        a[i++] = 2;
        num /= 2;
    }
    j = 3;
    while (j <= Math.sqrt(num) + 1) {
        if (num % j == 0) {
            a[i++] = j;
            num /= j;
        } else {
            j += 2;
        }
    }
    if (num > 1) {
        a[i++] = num;
    }
    int[] b = Arrays.copyOf(a, i);
    return b;
}

Đối với longcác giá trị:

static long[] getFactors(long value) {
    long[] a = new long[63];
    int i = 0;
    long num = value;
    while (num % 2 == 0) {
        a[i++] = 2;
        num /= 2;
    }
    long j = 3;
    while (j <= Math.sqrt(num) + 1) {
        if (num % j == 0) {
            a[i++] = j;
            num /= j;
        } else {
            j += 2;
        }
    }
    if (num > 1) {
        a[i++] = num;
    }
    long[] b = Arrays.copyOf(a, i);
    return b;
}

-2

Điều này có lẽ không phải lúc nào cũng nhanh hơn nhưng lạc quan hơn về việc bạn tìm thấy một ước số lớn:

  1. N là số của bạn
  2. Nếu là số nguyên tố thì return(N)
  3. Tính số nguyên tố cho đến khi Sqrt(N)
  4. Đi qua các số nguyên tố theo thứ tự giảm dần (lớn nhất trước)
    • Nếu N is divisible by Primesau đóReturn(Prime)

Chỉnh sửa: Ở bước 3, bạn có thể sử dụng Sàng của Eratosthenes hoặc Sàng Atkins hoặc bất cứ thứ gì bạn thích, nhưng bản thân rây sẽ không tìm thấy bạn là yếu tố chính lớn nhất. (Đó là lý do tại sao tôi không chọn bài đăng của SQLMenace làm câu trả lời chính thức ...)


1
Bạn không cần thực hiện bao thanh toán thử nghiệm để xác định xem đó có phải là số nguyên tố (bước 2) không? Ngoài ra, hãy xem xét việc tìm hệ số nguyên tố lớn nhất của 15. Các số nguyên tố lên đến sqrt (15) là 2 và 3; nhưng yếu tố chính lớn nhất là 5, phải không? Tương tự với 20.
Jonathan Leffler

-3

Tôi nghĩ sẽ tốt hơn nếu lưu trữ ở đâu đó tất cả các số nguyên tố có thể nhỏ hơn n và chỉ cần lặp qua chúng để tìm ra số chia lớn nhất. Bạn có thể lấy số nguyên tố từ Prime-numbers.org .

Tất nhiên tôi cho rằng số của bạn không quá lớn :)


-3

Không phải là nhanh nhất nhưng nó hoạt động!

    static bool IsPrime(long num)
    {
        long checkUpTo = (long)Math.Ceiling(Math.Sqrt(num));
        for (long i = 2; i <= checkUpTo; i++)
        {
            if (num % i == 0)
                return false;
        }
        return true;
    }

Đây không phải là một câu trả lời cho câu hỏi. ;-) Câu hỏi là về việc tìm ra yếu tố chính lớn nhất, không kiểm tra tính nguyên thủy.
Hans-Peter Störr

Sẽ hiệu quả hơn nhiều khi khởi tạo vòng lặp của bạn là (dài i = 3; i <checkUpTo; i + = 2)
cjk

-3

Đây là chức năng tương tự @ Triptych được cung cấp như một trình tạo, cũng đã được đơn giản hóa một chút.

def primes(n):
    d = 2
    while (n > 1):
        while (n%d==0):
            yield d
            n /= d
        d += 1

số nguyên tố tối đa có thể được tìm thấy bằng cách sử dụng:

n= 373764623
max(primes(n))

và một danh sách các yếu tố được tìm thấy bằng cách sử dụng:

list(primes(n))

-6
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include <time.h>

factor(long int n)
{
long int i,j;
while(n>=4)
 {
if(n%2==0) {  n=n/2;   i=2;   }

 else
 { i=3;
j=0;
  while(j==0)
  {
   if(n%i==0)
   {j=1;
   n=n/i;
   }
   i=i+2;
  }
 i-=2;
 }
 }
return i;
 }

 void main()
 { 
  clock_t start = clock();
  long int n,sp;
  clrscr();
  printf("enter value of n");
  scanf("%ld",&n);
  sp=factor(n);
  printf("largest prime factor is %ld",sp);

  printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);
  getch();
 }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.