Điều gì sẽ là một thuật toán thích hợp để nhân tố số trong phạm vi vài tỷ?


8

Hiện tại tôi đang học Python và cho tôi lý do để áp dụng những gì tôi đang học Tôi đang gặp phải một số vấn đề trên Project Euler

Tôi hiện đang ở số 3, để xác định hệ số nguyên tố cao nhất của số đã nói.

Tôi đã suy luận rằng tôi cần phải có hai thuật toán, một để xác định tính nguyên thủy và thứ hai liên quan đến việc tìm các yếu tố của số.

Vì vậy, tôi đã đọc các bài viết trên Wiki . Cố gắng xác định những gì có thể là thuật toán tốt nhất để sử dụng và làm thế nào để đi về nó.

Nhưng đã được một thời gian kể từ khi tôi thực hiện một số chương trình dựa trên toán học khó và tôi đang vật lộn để bắt đầu ở đâu đó.

Tôi đang xem xét sử dụng phương pháp nhân tố hóa của Fermat với sự bao gồm Thử nghiệm của Bộ phận nhưng tôi không muốn làm cho một cái gì đó quá phức tạp Tôi không muốn phá vỡ RSA Tôi chỉ muốn hai thuật toán phù hợp với vấn đề của mình và đó là câu hỏi của tôi.

Những thuật toán nào bạn sẽ sử dụng để kiểm tra tính nguyên thủy / bao thanh toán một số phù hợp với vấn đề hiện tại?

Biên tập

Cảm ơn tất cả các câu trả lời và hiểu biết của bạn, chúng rất hữu ích Tôi đã nêu lên tất cả những gì hữu ích thông qua lời khuyên hoặc thông qua kinh nghiệm của Euler. Cái tôi đánh dấu là đúng chỉ đơn giản là hữu ích nhất vì nó đã cho tôi một nơi thích hợp để bắt đầu từ đó là một cú hích đúng hướng. Cảm ơn lần nữa =)


Những vấn đề như vậy có thể sử dụng tốt nhất xử lý song song.
NoChance

Có thể bạn nói chung là đúng, nhưng đối với người dự án dự án, điều quan trọng hơn là tìm một thuật toán "thông minh". Chúng nhanh hơn rất nhiều so với cách tiếp cận song song lực lượng vũ phu.
sebastiangeiger

Đây là một vấn đề khó khăn về mặt toán học và bạn sẽ không tìm thấy một giải pháp lý tưởng .
DeadMG

Câu trả lời:


5

Cách tiếp cận của tôi cho những vấn đề đó thường là vấn đề này: xây dựng thuật toán đơn giản nhất có thể để giải quyết nó, thường là cách tiếp cận ngây thơ mạnh mẽ, và sau đó kiểm tra / tính toán xem liệu nó có quá chậm hay không. Hầu hết thời gian là đủ tốt. Khi không phải là bạn có một điểm khởi đầu rõ ràng để làm việc và tối ưu hóa mọi thứ xung quanh cho đến khi thuật toán đủ hiệu quả.

Đây là một thuật toán đơn giản để giải quyết vấn đề 3 trên Project Euler (bằng C, nhưng việc dịch nó sang Python nên không quan trọng):

#include <stdio.h>
#include <math.h>

int isPrime(int n){
    int i;

    if (n==2)
        return 1;

    if (n%2==0)
        return 0;
    for (i=3;i<sqrt(n);i+=2)
        if (n%i==0)
            return 0;
    return 1;
}

int main(){
    long long int n = 600851475143;
    int i = 3;

    while (i<50000){
        if (isPrime(i))
            if (n%i==0)
                printf("%d\n",i);
        i+=2;
    }
    return 0;
}

1
Tôi muốn sử dụng isPrimelà quá mức cần thiết. Chỉ cần làm n/=2trong khi n%2==0và sau đó bắt đầu ivới 3 và sau đó lặp if (n%i==0) n/=i; else i+=2;là đủ (tốt, nó có thể được dừng lại một lần i*i > n).
Herby

1
Kinh nghiệm giải quyết euler dự án của tôi là phương pháp này đang làm việc cho các vấn đề trước đó nhưng bạn có thể phải tinh chỉnh nó khi giải quyết những vấn đề phức tạp hơn.
sebastiangeiger

@Sebastian, tôi đang gặp vấn đề 73, và vâng, con đường tiếp cận ngây thơ nhất ngừng hoạt động. Nhưng này, tại sao lại phức tạp hóa mọi thứ trước khi bạn cần?
Daniel Scocco

2
@daniels: Tôi có thể bị câm ở đây. Làm thế nào để giải quyết vấn đề này? a) 50000 có vẻ độc đoán khủng khiếp. b) Bạn đang in ra tất cả các yếu tố chính, không chỉ cao nhất. c) Kiểm tra xem đó có phải là số nguyên tố hay không trước khi kiểm tra xem đó có phải là một yếu tố lãng phí không. d) 2 là số nguyên tố.
pdr

@pdr, a) các yếu tố chính không tăng nhanh như vậy, vì vậy tôi cho rằng 50000 sẽ đủ lớn. Nếu không, bạn luôn có thể lặp lại với 100000 hoặc sqrt (n). b) đúng, có nghĩa là bạn chỉ cần nhìn vào cái cuối cùng được in (tôi đã in tất cả chỉ để xem những gì đang diễn ra). c) Tôi đồng ý đảo ngược các bài kiểm tra sẽ hiệu quả hơn, nhưng không có sự khác biệt nào trong trường hợp này (nghĩa là bạn sẽ đạt được một phần nghìn giây) d) vâng tôi quên rằng trường hợp đặc biệt trên hàm isPrime () của tôi.
Daniel Scocco

4

Rất đáng để viết một số mã làm yếu tố tìm kiếm chính (về cơ bản là giống nhau) bởi vì bạn có thể sẽ sử dụng lại trong rất nhiều câu hỏi Euler khác. Bạn sẽ có thể cải thiện mã cho các câu hỏi sau này và có thể xem xét các bài kiểm tra nguyên thủy không toàn diện nếu bạn thấy nó không còn hiệu quả nữa, vì vậy tôi đề xuất cách tiếp cận đơn giản nhất bây giờ là:

  • Viết một vòng lặp đơn giản tìm tất cả các số nguyên tố (ví dụ: đối với mỗi số, kiểm tra tính chia hết của nó theo từng số nguyên tố được tìm thấy trước đó và nếu tất cả chúng đều thất bại, hãy thêm nó vào danh sách các số nguyên tố).
  • Cố gắng chia số bạn đang cố gắng tính theo từng số nguyên tố cho đến căn bậc hai của số.

4

Trên thực tế đây là một lĩnh vực nghiên cứu tích cực về Toán học và Khoa học Máy tính. Bài viết trên wikipedia cung cấp một cái nhìn tổng quan tốt:

http://en.wikipedia.org/wiki/Integer_factorization

Chọn bất kỳ thuật toán nào bạn thích / thấy thú vị, và hãy thử xem.

Có lẽ bạn sẽ phải đánh đổi: Hầu hết các thuật toán "tốt" đòi hỏi một chút nền tảng Toán học để thực sự hiểu (mặc dù bạn có thể thực hiện chúng mà không hoàn toàn hiểu chúng).

Nếu bạn không biết bắt đầu từ đâu, tôi khuyên bạn nên sử dụng rây bậc hai:

http://en.wikipedia.org/wiki/Quadratic_sieve

Nó không đòi hỏi kiến ​​thức toán học điên rồ, nhưng thực hiện tốt.


2

Tôi đã giải quyết một số vấn đề ProjectEuler một thời gian trước trong Ruby bằng cách sử dụng phân chia thử nghiệm với các số nguyên tố .

Tôi thấy rằng việc tạo ra các số nguyên tố quan trọng hơn nhiều so với thuật toán nhân tố thực tế. Ngay sau khi tôi thay thế phương pháp tạo số nguyên tố ngây thơ của mình bằng một cái rây, thời gian thực hiện của tôi đã giảm xuống một mức hợp lý.


1

Giữ cho nó rất đơn giản ...

Tìm các yếu tố của X: Tôi sẽ bắt đầu (n) tại 2 và làm việc với số nguyên (sàn chứ không phải tròn) của căn bậc hai của X. Nếu chia X cho n thì Y và Y là một số nguyên, cả n và Y là các yếu tố. Các giá trị thấp nhất của n sẽ mang lại giá trị cao nhất của Y.

Tính nguyên thủy của Y: Một lần nữa, lặp (m) từ 2 đến căn bậc hai của Y và xem Y / m có phải là số nguyên không. Nếu là thì Y không phải là số nguyên tố. Quay trở lại để tìm một yếu tố khác.

Nếu m chạm vào gốc của Y, bạn có số nguyên tố của mình. Đừng nhìn nữa. Y là câu trả lời.

Nếu n chạm vào gốc của X, sẽ không có bất kỳ yếu tố chính nào.


0

Vì đã có một giải pháp hoàn chỉnh, tôi sẽ đăng Haskell này một ...

--  Problem is to find the largest prime factor of 600851475143
module Factor (testval, bigfactor) where
  testval = 600851475143

  bf' :: Integer -> Integer -> Integer

  bf' f x | (f == x)         = f
          | ((mod x f) == 0) = bf' f (div x f)
          | True             = bf' (f+1) x

  bigfactor :: Integer -> Integer

  bigfactor x | (x <  1) = error "Parameter less than 1"
              | (x == 1) = 1
              | True     = bf' 2 x

Về cơ bản, không cần phải kiểm tra tính nguyên thủy. Nếu bạn phân chia các yếu tố bạn tìm thấy (và đảm bảo rằng bạn xử lý các yếu tố lặp lại), thì yếu tố không phải là số nguyên tố không bao giờ có thể xảy ra, bởi vì yếu tố không chính là sản phẩm của các yếu tố nguyên tố nhỏ hơn.

Đã tải và chạy nó với GHCi - ngay lập tức và giờ tôi đã có tổng cộng 4 (vâng, bốn!) Các vấn đề Euler đã được giải quyết.


0

Tôi cũng đang hình thành kiến ​​thức Python của mình và đã bắt đầu trả lời các vấn đề của Project Euler trên repo github của tôi: https://github.com/rentes/Euler .

Đối với Bài toán 3, tôi đã lập trình một giải pháp đơn giản dựa trên các tiền đề sau:

1) với số nguyên dương n, tôi bắt đầu chia nó cho 2, 3, ..., m và nếu tôi thấy rằng m là một thừa số nguyên tố, tôi thêm nó vào danh sách. Tôi không thêm vào danh sách bội số của các yếu tố chính đã được phát hiện. Chẳng hạn, 4 là bội số của 2, vì vậy 4 không được thêm vào danh sách này.

2) Sau đó tôi nhân từng số nguyên tố trong danh sách để xem nó có bằng n không. Nếu bằng nhau, chúng ta đã tìm thấy tất cả các thừa số nguyên tố của n. Nếu không, tiếp tục chia n cho số m tiếp theo, cho đến khi thay đổi tất cả các thừa số nguyên tố bằng n hoặc m đạt n.

Vui lòng xem https://github.com/rentes/Euler/blob/master/probols3.py để biết thêm chi tiết. Tôi đã thêm ý kiến ​​sẽ giúp bạn hiểu những gì tôi đã lập trình. Đó là một giải pháp đơn giản, và tôi chắc chắn đó không phải là giải pháp nhanh nhất, nhưng nó hoạt động và nó đủ đơn giản để hiểu.

Trân trọng

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.