30/09/2018, 16:42
Cách tìm lũy thừa của một số nguyên tố (tối ưu)
Mấy anh (chị) cho em ý tưởng về kiểm tra một số n có được viết dưới dạng n = a^b (với a là số nguyên tố, b > 1 thuộc N*)
Em viết được rồi nhưng trường hợp không tìm ra phải chạy hết vòng lập n lần, nhưng trong bài toán em đang làm giá trị lớn, phải duyệt từ 500.000 - 1.000.000.
Trung bình: 750.000*750.000 chạy rất lâu
Cảm ơn
Bài liên quan
Mình cũng không rõ chính xác đáp án thế nào, nhưng search thấy mấy link này khá giống yêu cầu của bạn
Diễn đàn Toán học
Trang chủ
Trang chủ - Diễn đàn Toán học
AKS primality test
The AKS primality test (also known as Agrawal–Kayal–Saxena primality test and cyclotomic AKS test) is a deterministic primality-proving algorithm created and published by Manindra Agrawal, Neeraj Kayal, and Nitin Saxena, computer scientists at the Indian Institute of Technology Kanpur, on August 6, 2002, in a paper titled "PRIMES is in P". The algorithm was the first to determine whether any given number is prime or composite within polynomial time. The authors received the 2006 Gödel Prize an AK...
Algorithm for detecting prime powers
không biết useful không mà cảm ơn rất nhiều
Hình như cái này là kiểm tra nó có phải là số nguyên tố hay không 1 cách nhanh nhất
Phương pháp của mình: vì n có cơ số a nhỏ nhất là 2. Nên b<= log2(n).
cho b chạy từ 2 đến log2(n):
Độ phức tạp:
=> dpt = O(log^2(n))
Bạn giỏi quá thế mà không nghĩ ra, mặc dù không chạy ra liền nhưng cũng cải thiện phần nào
@Gio có hàm pow(n,1/b) = căn bậc b của n nên chỉ mất O(1) thôi.
Mà làm v có vẻ đơn giản hơn ko nhỉ ;
Ý tưởng tương tự như gió nhưng ngược lại và DPT time thì lâu hơn.
Nếu N chẵn thì sqrt(N) khi nào = 1.0 thì N có dạng 2^b; // có thể dùng mảng lưu trc các giá trị 2^b, nếu b nhỏ.
Còn ko thì thoát.
Dễ thấy số nguyên tố 99% là lẻ (trừ số 2). -> n phải lẻ nếu n ko thuộc dạng 2^b.
Nếu N lẻ thì
Tìm số nguyên tố nhỏ hơn sqrt(N); (dùng sàng eratosthenes)
do b>1 nên -> mọi số <=sqrt(N) bình phương lên đều nhỏ hơn hoặc bằng N
Sau khi lọc được mảng SNT < sqrt(n) thì cho 1 vòng for từ i= 3->sqrt(n);
nếu i là số nguyên tố thì kiểm tra
log_bậc_i(n) được tính bằng CT: log(n)/log(i) với log() là log cơ số e tự nhiên. Dễ tìm thấy trong thư viện math.h
Độ phức tạp của thuật toán là O( sqrt(n)loglog( sqrt(n) ) );
Đây là em viết dựa trên ý tưởng của @Gio
nó chạy tầm 5s là ra, nhưng đề yêu cầu < 1s
Còn ý tưởng của @drgnz chưa hiểu rõ lắm, cảm phiền nói rõ 1 tí được không
Ta biết
n = a^b
-> log_a(n) = log_a(a^b) = b
Vì b là nguyên dương và lớn hơn 1, nên ta chỉ cần tìm b = log_a(n) sao cho b 1 số nguyên dương là đc
-> vì b min = 2 -> cần duyệt sqrt(n) để tránh sót và vừa đủ, ko dư thừa.
1 vòng for chạy từ i = 3-> sqrt(n), với mỗi i, nếu i là số nguyên tố ta kiểm tra xem log_i(n) có phải là số nguyên hay ko. Nếu ko tiếp tục, nếu phải, thoát chương trình.
log_i() có CT tính ở trên.
Để kiểm tra chính xác có phải là log_a(n) là 1 số nguyên không, thì mình dùng cách này.
Nếu muốn tối ưu hơn nữa.Bạn KT xem N có ở dạng a^2 không (chỉ mất O(1) thôi do có sàng + 1 câu if như trên). Rồi giảm xuống thành căn3 của N. Và duyệt đến căn3 của N thì sẽ tiết kiệm thêm đc nữa.
Bạn có thể tham khảo code của mình nhưng max n chỉ đc 10^12 th do giới hạng của mảng nguyên tố là 1m. ^^
Ideone.com
Ideone.com
Ideone is something more than a pastebin; it's an online compiler and debugging tool which allows to compile and run code online in more than 40 programming languages.
Tối ưu lại hàm check là dc mà.
t<<=1 trong vòng lặp for có ý nghĩa gì vậy, Cảm ơn
Là dịch trái 1 bit <=> t=t*2. Nhưng dịch bit sẽ nhanh hơn
Có chạy từng bước cũng thấy nó t *= 2;
Ủa mà sao dịch 1 bit lại t *= 2 nhỉ, theo cách tính nào vậy
Thời gian nó cũng same same nhau, tầm 2,5s - 3s
Mấu chốt vẫn là hàm kt snt. Nếu dùng thuật toán Rabin-Miller sẽ chạy trong O(logn). Bạn tìm hiểu cách cài đặt trên wiki có nói rất rõ đấy
Cách mình làm là : giả sử số nhập vào là int inputNumber
Ok, mình sẽ thử xem nó cải thiện không
Để mình xem thử nó có cải thiện thời gian không