2009-12-09 30 views
6

Tôi đang cố gắng viết một chương trình để tìm yếu tố chính lớn nhất của một số rất lớn, và đã thử một số phương pháp với sự thành công khác nhau. Tất cả những gì tôi đã tìm thấy cho đến nay đã không thể tin được chậm. Tôi có một ý nghĩ, và tự hỏi nếu điều này là một cách tiếp cận hợp lệ:Các vấn đề với số nguyên

long number = input; 

while(notPrime(number)) 
{ 
    number = number/getLowestDivisiblePrimeNumber(); 
} 

return number; 

Cách tiếp cận này sẽ mất một đầu vào, và sẽ làm như sau:

200 -> 100 -> 50 -> 25 - > 5 (cửa sổ mới)

90 -> 45 -> 15 -> 5 (cửa sổ mới)

Nó chia currentNum nhiều lần bởi các số chia hết cho nhỏ nhất (thường xuyên nhất 2 hoặc 3) cho đến khi currentNum chính nó là nguyên tố (có không có số nguyên tố có thể chia nhỏ hơn so với số bình phương của currentNum) và giả định đây là số tiền lớn nhất est yếu tố chính của đầu vào ban đầu.

Điều này sẽ luôn hoạt động? Nếu không, ai đó có thể cho tôi một counterexample?

-

EDIT: Bởi rất lớn, tôi có nghĩa là khoảng 2^40 hoặc 10^11.

+5

Tôi muốn xem việc triển khai hàm 'notPrime()' huyền diệu của bạn. :) –

+3

heh, thật dễ dàng: notPrime (n) = (getLowestDivisiblePrimeNumber (n) == n). –

+0

Thành thật mà nói, tôi sử dụng trong khi (đúng) ở đó, nó chỉ là dễ dàng hơn để giải thích theo cách này. Phương thức getLowestDivisiblePrime của tôi đề cập đến danh sách chính ArrayList ; Nếu không có số nguyên tố divisible trong primList, nó sẽ tìm số nguyên tố tiếp theo để thêm vào primList và tiếp tục làm như vậy cho đến khi tìm thấy số nguyên tố 'số' chia hết cho (và sau đó sẽ tham chiếu đến danh sách số nguyên tố lớn hơn) , hoặc cho đến khi số nguyên tố lớn nhất trong danh sách chính lớn hơn sqaureroot của 'số'. Không có phép thuật ở đó, mặc dù tôi hy vọng nó khá hiệu quả. = P – Jonathan

Trả lời

16

Điều này sẽ luôn hoạt động do Unique Prime Factorization Theorem.

+0

Cảm ơn bạn đã trích dẫn. =) – Jonathan

+2

Đối với các trường hợp góc, 0 và 1 không phải là số nguyên tố cũng như tổng hợp và được ký dài, bạn sẽ cần phải tìm ra cách bạn muốn xử lý các số âm. –

2

Bạn đang cố gắng tìm số prime factors của một số. Những gì bạn đang đề xuất sẽ hoạt động, nhưng vẫn sẽ chậm đối với số lượng lớn .... bạn nên biết ơn vì điều này, vì hầu hết bảo mật hiện đại được xác định trên đây là một vấn đề khó khăn.

+0

Trên chấm! Điều đầu tiên xuất hiện trong đầu là RSA. –

3

Chắc chắn nó sẽ hoạt động (xem Mark Byers' answer), nhưng đối với các đầu vào "rất lớn" có thể mất quá nhiều thời gian. Bạn nên lưu ý rằng cuộc gọi của bạn để getLowestDivisiblePrimeNumber() ẩn vòng lặp khác, do đó, điều này chạy ở O (N^2) và tùy thuộc vào ý nghĩa của "rất lớn", nó có thể phải hoạt động trên BigNums sẽ chậm.

Bạn có thể tăng tốc độ lên một chút, bằng cách lưu ý rằng thuật toán của bạn không bao giờ cần kiểm tra các yếu tố nhỏ hơn so với giá trị cuối cùng được tìm thấy.

+0

Tôi sẽ làm điều đó, cảm ơn bạn. =) – Jonathan

+0

Mặc dù là cầu kỳ, nó nói 'dài' và sử dụng 'Java' trong thẻ câu hỏi, do đó, đó chỉ là 2 ** 63 và không phải là một loại BigNum của vấn đề. Mặt khác, tài liệu nằm. :) –

+0

@dalke: Ack. Nhìn thấy những từ "rất lớn" kinda bị mắc kẹt trong một rut. Và tôi nghĩ rằng phiên bản cải tiến có thể chạy trong thời gian tuyến tính (chậm), mặc dù phương pháp OP gợi ý sẽ sử dụng nhiều không gian ... – dmckee

21

Phương pháp này sẽ hoạt động nhưng sẽ chậm. "Con số của bạn lớn đến mức nào?" xác định phương thức sử dụng:

+1

Tôi bị ấn tượng bởi các tham chiếu của bạn đối với các thuật toán mà tôi chưa bao giờ nghe, nhưng: Không phải những thuật toán này phù hợp hơn cho việc tìm kiếm * tất cả * số nguyên tố lên đến một giới hạn nhất định, hơn là để bao thanh toán một số duy nhất? –

+0

Tôi đồng ý với Carl. Trong khi tôi không thể tuyên bố điều này như là một thực tế (tôi đã không nghiên cứu về các phương pháp được đề cập ở trên), tôi tin rằng đây là một phương pháp rất hiệu quả cho việc tìm kiếm các yếu tố chính lớn nhất. Làm thế nào tôi thực hiện notPrime() - hay đúng hơn,! Prime() - là một vấn đề khác hoàn toàn. – Jonathan

+0

@ Jonathan: Làm thế nào lớn là "rất lớn"? –

1

Từ một tìm kiếm nhanh tôi chỉ làm, cách nhanh nhất được biết đến yếu tố một số là sử dụng phương pháp Elliptic Curve.

Bạn có thể thử ném số của mình tại bản trình diễn này: http://www.alpertron.com.ar/ECM.HTM.

Nếu điều đó thuyết phục bạn, bạn có thể thử ăn cắp mã (không vui, họ cung cấp liên kết đến nó!) Hoặc đọc lên lý thuyết về nó ở nơi khác. Có một bài viết Wikipedia về nó ở đây: http://en.wikipedia.org/wiki/Lenstra_elliptic_curve_factorization nhưng tôi quá ngu ngốc để hiểu nó. Rất may, đó là vấn đề của bạn, không phải của tôi! :)

0

Điều với Project Euler là thường có một phương pháp brute-force rõ ràng để thực hiện vấn đề, điều này sẽ mất khoảng mãi mãi. Khi các câu hỏi trở nên khó khăn hơn, bạn sẽ cần phải thực hiện các giải pháp thông minh.

Một cách bạn có thể giải quyết vấn đề này là sử dụng vòng lặp luôn tìm thấy hệ số nhỏ nhất (số nguyên dương) của một số. Khi yếu tố nhỏ nhất của một con số là con số đó, thì bạn đã tìm ra nhân tố chính yếu nhất!

Chi tiết mô tả thuật toán:

Bạn có thể làm điều này bằng cách giữ ba biến:

Số bạn đang cố gắng yếu tố (A) Một cửa hàng ước hiện tại (B) Một cửa hàng ước lớn nhất (C)

Ban đầu, hãy để (A) là số bạn quan tâm - trong trường hợp này là 600851475143. Sau đó để (B) là 2. Có điều kiện kiểm tra nếu (A) chia hết cho (B) . Nếu nó chia hết, chia (A) bằng (B), đặt lại (B) thành 2, và quay trở lại để kiểm tra xem (A) có chia hết cho (B) hay không. Khác, nếu (A) không chia hết cho (B), số gia tăng (B) bằng +1 và sau đó kiểm tra xem (A) có chia hết cho (B) hay không. Chạy vòng lặp cho đến khi (A) là 1. (3) bạn trở lại sẽ là số nguyên tố lớn nhất của 600851475143.

Có rất nhiều cách bạn có thể làm điều này hiệu quả hơn - thay vì tăng đến số nguyên tiếp theo, bạn có thể tăng lên số nguyên nguyên nhất thiết tiếp theo, và thay vì giữ một kho số chia lớn nhất, bạn chỉ có thể trả về số hiện tại khi ước số duy nhất của nó là chính nó. Tuy nhiên, thuật toán tôi mô tả ở trên sẽ chạy trong vài giây bất kể.

Việc thực hiện trong python là như sau: -

def lpf(x): 
     lpf = 2; 
     while (x > lpf): 
       if (x%lpf==0): 
         x = x/lpf 
         lpf = 2 
       else: 
         lpf+=1; 
     print("Largest Prime Factor: %d" % (lpf)); 

def main(): 
     x = long(raw_input("Input long int:")) 
     lpf(x); 
     return 0; 

if __name__ == '__main__': 
    main() 

Ví dụ: Hãy tìm ra thừa số nguyên tố lớn nhất của 105 sử dụng phương pháp mô tả ở trên.

Cho (A) = 105. (B) = 2 (chúng tôi luôn bắt đầu bằng 2) và chúng tôi chưa có giá trị cho (C).

Có (A) chia hết cho (B) không? Số Tăng (B) bằng +1: (B) = 3. Is Is (A) chia hết cho (B)? Vâng. (105/3 = 35). Ước số lớn nhất được tìm thấy cho đến nay là 3. Hãy (C) = 3. Cập nhật (A) = 35. Đặt lại (B) = 2.

Bây giờ, (A) chia hết cho (B)? Số Tăng (B) +1: (B) = 3. Có (A) chia hết cho (B)? Số Tăng (B) bằng +1: (B) = 4. Có (A) chia hết cho (B)? Số tăng (B) +1: (B) = 5. Có (A) chia hết cho (B)? Vâng. (35/5 = 7). Ước số lớn nhất mà chúng tôi đã tìm thấy trước đó được lưu trữ trong (C). (C) hiện tại 3. 5 lớn hơn 3, vì vậy chúng tôi cập nhật (C) = 5. Chúng tôi cập nhật (A) = 7. Chúng tôi thiết lập lại (B) = 2. Sau đó chúng ta lặp lại quá trình cho (A), nhưng chúng ta sẽ tiếp tục tăng (B) cho đến khi (B) = (A), bởi vì 7 là số nguyên tố và không có ước số nào ngoài chính nó và 1. (Chúng ta đã có thể dừng khi (B)> ((A)/2), vì bạn không thể có ước số nguyên lớn hơn một nửa số - ước số nhỏ nhất có thể (trừ 1) của bất kỳ số nào là 2!)

Vì vậy điểm chúng tôi trở lại (A) = 7.

Hãy thử thực hiện một vài thao tác này một cách thủ công và bạn sẽ nhận được ý tưởng

Các vấn đề liên quan