Trải qua nhiều thế kỷ, con người đã có biết bao nỗ lực tìm kiếm thuật toán hữu hiệu để tìm hiểu số nguyên tố. Bài toán xác định một số có phải là số nguyên tố hay không được xếp vào loại NP - không có thuật toán tất định (một số thuật toán khác như Miller-Rabin là loại thuật toán dựa trên xác suất) trong thời gian đa thức. Cho đến năm 2002, ba nhà khoa học người Ấn Độ là Agrawal, Kayal, Saxena đăng bài báo về thuật toán AKS đưa ra phương pháp kiểm tra số nguyên tố trong thời gian đa thức, đã phá vỡ “lời nguyền“ thiên niên kỷ (khởi đầu từ thuật toán Sàng Eratosthenes ca. 240BC).
Định lý Fermat nhỏ
Đây là định lý làm nền tảng cho thuật toán này. Định lý được phát biểu như sau:
Nếu p là số nguyên tố, và a là một số nguyên không chia hết cho p, ta luôn có:
ap≡p(modp)
Bạn có thể tìm thấy rất nhiều phương pháp chứng minh định lý thú vị này. Mình xin giới thiệu một phương pháp chứng minh rất đẹp dưới đây.
Chứng Minh
Gọi S={1,2,…,p−1} xét tập hợp aS={1a,2a,…,(p−1)a}(modp). Nhận xét:
Tất cả các phần tử ai,1≤i≤p−1 không chia hết cho p
Với 1≤i,j≤p−1, nếu ai≡aj(modp) mà gcd(a,p)=1 nên i≡j(modp)⟹i=j
Từ 1 & 2 ta suy ra tất cả các phần tử của aS(modp) là phân biệt nhau, như vậy ta có:
Vì n là số nguyên tố nên an−a chia hết cho n. Mặt khác, tất cả các tham số (kn)=k!(n−k)!n! đều là số nguyên nên cũng đều phải chia hết cho n.
Vế 2: Nếu (x+a)n≡xn+a(modn)với mọi a,x là biến số bất kỳ thì nlà số nguyên tố.
Ta chứng minh bằng phản chứng. Nếu n là hợp số, gọi q là một thừa số nguyên tố của n, và qk∣n (n chia hết cho qk). Xét tham số (qn)xqan−q, ta có:
(qn)không chia hết cho qkvì n!trên tử số đã chia cho q! ở mẫu số nên không còn đủ lũy thừa của qk
an−q nguyên tố cùng nhau với qk
Vậy tham số của xq là (qn)an−q không chia hết cho n với mọi a,x bất kỳ (trái với giả thiết)
Từ chứng minh của vế 1 & vế 2, ta kết luận định lý trên đúng.
Mấu chốt của thuật toán
Định lý trên làm tiền đề mở ra một phương pháp mới để kiểm tra n có phải số nguyên tố hay không bằng cách chọn một giá trị a và thay vào định lý trên để kiểm tra có thỏa điều kiện không. Tuy nhiên, để tính được (x+a)n, ta vẫn phải tính các hệ số của đa thức khi khai triển ra và vì thế chúng ta vẫn phải tính n+1 lần làm cho độ phức tạp thuật toán vẫn không giảm. Tuy nhiên ta có thể hạ bậc của (x+a)n≡xn+a bằng cách đem cả hai vế chia lấy phần dư cho đa thức xr−1, với một gía trị r được chọn đủ nhỏ, đa thức phần dư sẽ có bậc nhỏ hơn r và làm giảm độ phức tạp thuật toán.
Tính nhanh (x+a)nmodxr−1
Để ý rằng, để tính (x+a)nmod(xr−1), chúng ta có thể áp dụng phương pháp liên tục bình phương và chia lấy phần dư để tiết kiệm tính toán thay vì phải tính n+1hệ số rồi mới đem chia.
Nghĩa là, thay vì dạng gốc, ta sẽ kiểm tra dạng rút gọn như dưới đây:
(x+a)n≡xn+a(xr−1,modn)(∗∗)
Tiếp tục, tính nhanh xn+amodxr−1
Biểu thức trên có thể tính dễ dàng trong O(1) như sau:
xn+amodxr−1={a+1, if r∣nxnmodr+a, otherwise
Ví dụ:x5+3modx3−1=x2+3, và x4+2modx2−1=3.
Bạn có thể tự chứng minh điều này dễ dàng.
Đây là ý tưởng chính và là điểm mấu chốt của thuật toán AKS. Kể từ phần sau phần này, mình sẽ chỉ đưa ra tóm tắt ý tưởng mà không chứng minh vì trong bài báo gốc đã chứng minh khá ổn, các bạn đọc đến đây, có thể tự tham khảo lại từ bài báo gốc.
Định lý AKS (định lý chính)
Bây giờ vấn đề đặt ra là, có n là hợp số và vẫn thỏa mãn điều kiện (**): (x+a)n≡xn+a(xr−1,modn)nhưng lại không thỏa (*): (x+a)n≡xn+a(modn). May mắn thay, vấn đề này được giải quyết thông qua định lý AKS, phát biểu lại từ thuật toán:
Cho giá trị r nguyên tố cùng nhau với n sao cho or(n)>log2n, với or(n) là cấp của nhóm nhân (Z/rZ)×( hay nói cách khác, các phần tử nimodr,với 1≤i≤log2n phân biệt nhau). Giả sử với mọi giá trị 1≤a≤O(rlogn)đều thỏa mãn tính chất (x+a)n≡xn+a(xr−1,modn), và gcd(a,n)=1thì n hoặc là mộtsố nguyên tố, hoặc là mộtlũy thừa của một số nguyên tố.
Sự tồn tại của giá trị r
Từ đầu đến giờ, chúng ta đã đi thông qua các ý tưởng sau:
Dùng định lý Fermat nhỏ mở rộng để biến bài toán thành dạng đa thức
Giảm bậc của đa thức gốc bằng cách modulo cho xr−1
Chứng minh rằng với một số giá trị của r và 1≤a≤O(rlogn) thỏa mãn (**), thì sẽ là số nguyên tố hoặc lũy thừa của một số nguyên tố.
Nghĩa là, ta sẽ xét tất cả các giá trị a trong khoảng 1≤a≤O(rlogn) để kiểm tra n có phải số nguyên tố hay không. Điều cuối cùng, ta cần chứng minh là tồn tại một giá trị r tốt, phù hợp để làm cho độ phức tạp bài toán thành đa thức với bổ đề chứng minh về sự tồn tại của r:
Tồn tại r=O(logn), và gcd(r,n)=1 sao cho or(n)>log2n, với or(n)là cấp của nhóm nhân (Z/rZ)×.
Demo
Lời bàn
Đây là chi tiết về các bước của thuật toán trong bài báo:
Thuật toán AKS có độ phức tạp khoảng O(r3/2(logn)3) với chi tiết như sau:
Kiểm tra n có phải là một lũy thừa cần O((logn)3)
Tìm kiếm r thỏa or(n)>(logn)2 cần O(r(logn)2)
Kiểm tra gcd(a,n)>1cho các giá trị a≤r cần O(r(logn)2)
Kiểm tra (x+a)n≡xn+a(modn,xr−1)cho a=1,2,…[rlogn], mỗi bước cần O(r3/2(logn)3)
Tóm lại, thuật toán bị ảnh hưởng lớn bởi cách chọn r, tuy nhiên có một giới hạn là r>(logn)2, điều này có nghĩa là thuật toán có giới hạn chặn dưới là O((logn)6)… Một con số khá ấn tượng, tuy rằng vẫn chưa thể so sánh với Miller-Rabin, nhưng dù sao cũng là cơ sở để chúng ta hy vọng về một phương pháp xuất sắc hơn trong tương lai.