Số học thuật toán (Algorithmic number theory) là một ngành toán học đang phát triển mạnh, nghiên cứu số học trên phương diện thuật toán. Ta cần chú ý rằng Số học là một trong những ngành toán học cổ nhất còn thuật toán lại là một khái niệm mới mẻ ra đời và phát triển từ trong thế kỉ XX. Số học thuật toán được xây dựng trên cơ sở những thành tựu của cả lý thuyết số học lẫn thuật toán.
Chuyên đề Thuật toán Số học Trần Quang Khải Chuyên đề THUẬT TOÁN SỐ HỌC I Gới thiệu chung Số học thuật toán (Algorithmic number theory) ngành toán học phát triển mạnh, nghiên cứu số học phương diện thuật toán Ta cần ý Số học ngành toán học cổ thuật toán lại khái niệm mẻ đời phát triển từ kỉ XX Số học thuật toán xây dựng sở thành tựu lý thuyết số học lẫn thuật toán Một toán tiếng đựoc giải kỉ XX toán thứ 10 Hilbert ‘Có tồn thuật toán tổng quát cho phép ta trả lời phương trình Diophantine cho trước có nghiệm hay không ?’ Phương trình Diophantine phương trình có dạng f(x, y, z, … ) = f(x, y, z, …) đa thức biến x, y, z, … có hệ số nguyên, biến nhận giá trị nguyên Bài toán Michiakêvích giải trọn vẹn câu trả lời phủ định, tức thuật toán Bài toán thứ 10 Hilbert giải thành tựu quan trọng số học thuật toán Số học thuật toán không phát triển thành tựu Số học sơ cấp, mà tận dụng thành tựu Số học đại, Đại số đại, Hình học đại số … Cũng ngành toán học - thuật toán khác, Số học thuật toán có toán NP, tức thuật giải thời gian đa thức, tiêu biểu toán phân tích số thừa số nguyên tố, thuật toán kiểm tra nguyên tố, … Trong viết này, ta đề cập tới vấn đề Số học thuật toán, sở toán học sơ cấp II Các phép tính với số nguyên Trong máy tính, số biểu diễn hệ nhị phân, việc mô tả dạng nhị phân làm cho phép tính trở nên đơn giản nhiều Để cho tổng quát, ta giả sử hai toán hạng có N bit (trong trường hợp số bít có nghĩa nhỏ N ta thêm vào đầu cho đủ) Phép cộng phép trừ Đối với phép cộng phép nhân số N bít, ta thực giống phép cộng trừ hệ thập phân : Thực cộng (hay trừ) từ phải sang trái (với bít ứng với số mũ nhỏ trước số mũ lớn sau) Phép nhân Đối với phép nhân, ta có thuật toán nhân Nga mô tả sau : Function Mult(a, b : Integer): Integer; Var c : Integer; Begin c := 0; repeat if Odd(b) then c := c + a; a := a shl 1; b := b shr 1; until b = 0; Mult := c; End; Nếu xét cho kĩ thực thuật toán nhân Nga có dạng với thuật toán nhân hai số phương pháp mà bình thường ta dùng để tính tay, có điều khác thao tác hệ nhị phân Thuật toán nhân Nga gồm N lần dịch bít, trường hợp tổng quát phải thực N/2 lần phép cộng, độ phức tạp tính toán N2 Sau đây, ta giới thiệu thuật toán nhân khác, phức tạp có độ phức tạp nhỏ Giả sử ta phải thực phép nhân với hai số có 2N bit A B Phân tích : A = a1*2N + a2 B = b1*2N + b2 AB = a1*b1 * 22N + (a1b2 + a2b1)*2N + a2b2 Ta ý phép nhân với luỹ thừa phép cộng có thời gian tỉ lệ với N Nhận xét : (a1+a2)(b1 + b2) - a1b1 - a2b2 = a1b2 + a2b1 Chuyên đề Thuật toán Số học Trần Quang Khải Do biết (a1+a2)(b1 + b2), a1b1, a2b2 tính a1b2 + a2b1 → Qui nhân hai số 2N bit lần nhân N bit số phép tính có thời gian tỉ lệ với N Nếu gọi F(n) thời gian nhiều để thực phép nhân hai số có 2n bit, ta có F(n) = 3F(n-1) + k2n (*) k số thể chi phí phép tính cộng dịch bit bước gọi đệ qui Chia hai vế (*) cho 2n ta F (n) F ( n − 1) = + k Do đó, F(n) = O(3n) = O( n log ) hay nói cách khác thời gian thực n n −1 2 phép nhân hai số N bít có độ phức tạp cỡ O( N log ) Phép chia Trong phần này, ta trình bày thuật toán chia hai số nhị phân có N bít A = (A1A2A3…AN) 2, B = (B1B2…BN)2 cho kết thương Q, dư R +Bước 1:Q ← 0, R ← 0, i ← +Bước 2: i = i+1 Nếu i > N → kết thúc thuật toán, ngược lại → Bước +Bước 3: R ← (R shl 1) or (A[i]) Nếu R ≥ B → Bước 4, ngược lại Bước +Bước 4: R ← R - B, C[i] = Thực Bước +Bước 5: C[i] = Thực Bước Hay ta mô tả chương trình : Procedure Divide(A, B : LongInt; var Q, R : LongInt); Var i : Integer; Begin Q := 0; R := 0; For i := to N Begin If (A and (1 shl (N-i)) 0) then R := (R shl 1)+1 else R := R shl 1; if R >= B then Begin Q := Q or (1 shl (N-i)); R := R - B; End; End; End; Đánh giá độ phức tạp: Thuật toán chia có độ phức tạp (N2) III Thuật toán Euclid Thuật toán Euclid Thuật toán Euclid dùng để tìm ước chung lớn hai số nguyên dương m, n Thuật toán tiến hành sau : Bước 0: Đặt a = m, b = n Bước 1: Nếu a > b ta thay a phần dư phép chia a cho b, ngược lại thay b phần dư phép chia b cho a Bước 2: Nếu a b 0, kết a + b, ngược lại thực bước Hay thuật toán mô tả hàm ngôn ngữ Pascal sau : Function Euclid(m, n : Integer) : Integer; Var a, b : Integer; Begin a := m; b := n; repeat if a > b then a := a mod b else b := b mod a; until (a = 0) or (b = 0); Chuyên đề Thuật toán Số học Trần Quang Khải Euclid := a + b; End; Ta có cách viết khác sau : Function Euclid1(m, n : Integer) : Integer; Var a, b, r : Integer; Begin a := m; b := n; repeat r := a mod b; a := b; b := r; until b = 0; Euclid := a; End; Trong số học ta biết với hai số nguyên dương m, n d ước chung chúng tồn hai số nguyên u, v cho u*m + v*n = d Từ thuật toán Euclid ta cụ cặp (u, v) : Ta ý bước vòng lặp repeat, a b tồn cặp (x, y) với x, y ∈ Z thoả mãn x*m + y*n = a (= b) Ban đầu a = m có cặp tương ứng (1, 0), cặp tương ứng với b = n (0, 1) : 1*m + 0*n = m = a 0*m + 1*n = n = b Trong vòng lặp, ta có phép gán a := a mod b, phép gán tương đương a := a - q*b q thương phép chia a cho b (q := a div b) Khi cặp (xa, ya) tương ứng với a biến đổi tương ứng xa := xa - q*xb ya := ya - q*yb Như vậy, a b biểu diễn dạng x*m + y*n kết ước chung a + b có cặp x, y tương ứng x a + xb , ya + yb Như vậy, thuật toán tìm cặp u, v sở thuật toán Euclid viết sau : Procedure Euclid2(m, n : Integer; var u, v : Integer); Var a, b, q, r : Integer; xa, ya, xb, yb, xt, yt : Integer; Begin a := m; b := n; xa := 1; ya := 0; xb := 0; yb := 1; repeat q := a div b; r := a mod b; a := b; b := r; xt := xa; yt := ya; xa := xb; ya := yb; xb := xt - q*xb; yb := yt - q*yb; until b = 0; u := xa; v := ya; Chuyên đề Thuật toán Số học End; Trần Quang Khải Đánh giá độ phức tạp thuật toán Euclid : Nếu ta gọi (ai, bi) cặp a, b vòng lặp thứ i, đánh số theo chiều ngược lại ( kết thúc (a 1, b1), trước (a2, b2), (a3, b3) … , (as, bs)) Ta chứng minh qui nạp max{ak, bk) ≥ Fk Fk số thứ k dãy Fibonaci Ta có công thức sau : +1 1+ n −1 − n ( ) + ( ) 2 5 Fn tăng theo hàm mũ, thuật toán Euclid có độ phức tạp lôgarit max(m, n) Ta ý cách đánh giá bỏ qua thời gian thực phép chia (mod) (trong máy tính lệnh CPU), nhiên thuật toán chia thực với hai số N bít nói chung khoảng N Do xét chi tiết, thuật toán Euclid có độ phức tạp cỡ O((log(max{m, n})3) Thuật toán Euclid nhị phân Sau đây, ta trình bày dạng khác thuật toán Euclid có độ phức tạp nhỏ Ta có nhận xét sau : ước chunh lẻ lớn hai số a, b không phụ thuộc vào phép biến đổi sau : + Chia a (hoặc b) a (hoặc b) chẵn + Thay a a - b Thuật toán mô tả sau : + Bước : a = m, b = n, dem = + Bước : Nếu a b chẵn → Bước ngược lại → Bước + Bước : dem = dem + 1, chia a b cho 2, Quay Bước + Bước : Chừng a chẵn chia a cho 2, thực tương tự với b + Bước : Nếu a = b → Bước 6, ngược lại → Bước 5.; + Bước : Nếu a > b → a := a - b, ngược lại → b := b - a Thực Bước + Bước : c := a * 2dem ( dịch c sanh trái số bit dem ) Thuật toán kết thúc c ước chung lớn cần tìm Ta môt tả chương trình Pascal sau : Function BinaryEuclid(m, n : Integer) : Integer; Var a, b, dem : Integer; Begin a := m; b := n; dem := 0; while (not Odd(a)) and (not Odd(b)) begin Inc(dem); a := a shr 1; b := b shr 1; end; repeat while not Odd(a) a := a shr 1; while not Odd(b) b := b shr 1; if a = b then Break; if a > b then a := a - b else b := b - a; until a = b; BinaryEuclid := a shl dem; End; Vì số đước mô tả dạng nhị phân nên rõ ràng phép chia thực đơn giản phép dịch phải Nếu m, n mô tả N bít phép dịch có chi phí N, phép trừ có chi phí N (xem phần II) Mặt khác, sau phép trừ phép dịch bít ta dễ thấy có không 2N lần dịch bit Do độ phức tạp thuật toán cỡ N2 hay log(max{m, n})2 Ta cần ý phép mod lệnh hệ thống nên số m, n không lớn (trong phạm vi 231) thuật toán Euclid mục chạy nhanh thuật toán mô tả Còn Fn = Chuyên đề Thuật toán Số học Trần Quang Khải ta phải làm việc với số lớn thuật toán Euclid nhị phân thích hợp Thuật toán độ phức tạp nhỏ mà có lợi khác ta phải thực phép dịch bít phép trừ phép tính đơn giản, thuật toán Euclid phải thực phép chia viết phức tạp IV Giải phương trình nghiệm nguyên tuyến tính Phương trình đồng dư ax ≡ b(mod c) (*) Với a, b, c số nguyên dương Gọi d ước chung lớn a c Kết từ số học cho ta phương trình có nghiệm b chia hết d (*) có nghiệm có vô số nghiệm dạng x = x + k * e với k ∈ Z, e = c / d x0 nghiệm (*) Như vậy, ta dễ dàng kiểm tra phương trình có nhiệm hay không Vấn đề lại tìm nghiệm x thoả mãn phương trình Ta ý thuật toán Euclid chí hai số u, v cho u *a + v * c = d, tức u*a ≡ d (mod c)⇒ x0 = u * (b / d) (chú ý phương trình có nghiệm ⇔ b chia hết cho d) a*x0 ≡ b (mod c), tức x0 thoả mãn (*) Chương trình Pascal giải phương trình (*) sau : Procedure Solve1(a, b, c : Integer); Var d, e, b1, u, v : Integer; Begin Euclid2(a, c, u, v); d := u*a + v*c; if b mod d then Writeln(‘No solution ’) else begin e := c div d; b1 := b div d; Writeln(‘Equation has infinite solution’); Write(‘All solutions have form : ); Writeln(‘ x = ’, u*b1 ,‘ + k*‘, e); end; End; Phương trình Diophantine tuyến tính dạng a*x + b*y = c (**) với a, b, c ∈ Z+ Ta dễ thấy phương trình Diophantine đưa giải phương trình đồng dư tuyến tính (**) ⇔ ax ≡c (modb ) y= c −ax b Việc giải phương trình đồng dư tuyến tính đựơc trình bày mục Chú ý : Gọi d = UCLN(a, b) a1 = a / d b1 = b / d (**) có nghiệm c ≡ (mod d) (**) có nghiệm có vô số nghiệm, công thức nghiệm : (x, y) = (x0, y0) + k (-b1, a1) Với (x0, y0) nghiệm (**) Định lý đồng dư Trung Hoa Định lý : Cho m số nguyên dương a1, a2, a3, … am đôi nguyên tố nhau, m số nguyên b 1, b2, b3, … bm thoả mãn ≤ bi ≤ - ∀i= 1, 2, …, m Đặt M = a1*a2*…*am Khi tồn số nguyên x thoả mãn : ≤ x ≤ M - x ≡ bi (mod ai) ∀i = 1, 2, …, m Định lý đồng dư Trung Hoa trình bày chứng minh hầu hết giáo trình Số học Sau ta tìm hiểu thuật toán cụ thể số x Chuyên đề Thuật toán Số học Trần Quang Khải Ta ý nghiệm tương ứng với k ràng buộc đầu (ứng với số a 1, b1, a2, b2, … ak, bk) có dạng x = xk + Mk Trong Mk = a1* a2* …* ak xk nghiệm thoả mãn định lý đồng dư Trung Hoa tương ứng với a1, b1, a2, b2, … ak, bk Dễ thấy xk+1 nghiệm không âm nhỏ thoả mãn hệ x ≡ bk+1(mod ak+1) x ≡ xk (mod Mk) Kết cuối cùng, số thỏa mãn toán xm Như vậy, ta đưa việc giải m phương trình m-1 lần giải hệ hai phương trình Ta giải hệ hai phương trình sau : Vì x ≡ xk (mod Mk) nên x = xk + y * Mk, toán trở thành tìm nghiệm không âm nhỏ phương trình đồng dư xk + y * Mk ≡ bk+1(mod ak+1) Ở phần 1, ta giải phương trình cho nhiệm có dạng y = y0 + t*ak+1 (vì ak+1 Mk nguyên tố nhau) Từ công thức nghiệm, dễ thấy y không âm nhỏ = y0 mod ak+1 V Thuật toán kiểm tra nguyên tố Bài toán : Kiểm tra số n > cho trước có phải nguyên tố hay không ? Tiếp cận toán qua số thuật toán đơn giản Theo định nghĩa số nguyên tố: Một số nguyên tố ước không tầm thường Từ ta viết hàm kiểm tra nguyên tố sau : Function Prime(n : Integer) : Boolean; Var i : Integer; Begin Prime := False; For i := to n-1 if n mod i = then Exit; Prime := True; End; Ta thấy rõ thuật toán chi phí trường hợp xấu lên tới O(n) Ta thấy thô dựa vào nhận xét : Nếu n hợp số phải có ước nhỏ n , ta cần xét ước không n Thuật toán cải tiến mô tả sau : Function Prime(n : Integer) : Boolean; Var i : Integer; Begin Prime := False; For i := to Trunc(Sqrt(n)) if n mod i = then Exit; Prime := True; End; Dễ thấy thuật toán cải tiến trường hợp tồi O( n ), nhiên ta cần ý thuật toán cải tiến khác thuật toán ban đầu n số nguyên tố, với n hợp số hai thuật toán kết thúc sau số phép tính Ta có hướng cải tiến nhận xét thêm : Nếu n hợp số phải có ước nguyên tố ≤ n , thay tìm ước tất số khoảng từ đến n , ta xét số nguyên tố khoảng Nhưng vấn đề dược đặt làm để có danh sách số nguyên tố không vượt n , thấy chi phí tạo danh sách số nguyên tố không n Tuy vậy, trường hợp phải kiểm tra nhiều số n ta áp dụng phương pháp Trong trường hợp danh sách số nguyên tố, ta hạn chế tập tìm kiếm phương pháp sau : Chọn số k < n, UCLN(n, k) > rõ ràng n hợp số, ngược lại ta hạn chế tập tìm kiểm số khoảng đến n mà phải nguyên tố với k Thuật toán mô tả sau : Chuyên đề Thuật toán Số học Trần Quang Khải Function Prime(n, k : Integer) : Boolean; Var List : array[1 maxk] of Integer; j, i, l : Integer; Begin Prime := False; if Euclid(n, k) > then Exit; {Hàm Euclid lấy ước chung lớn hai số nguyên dương môt tả phần III} l := 0; for i := to k-1 if Euclid(i, k) = then begin Inc(l); List[l] := i; end; for i := to l if n mod L[i] = then Exit; j := k; while Sqr(j) < n begin for i := to l if n mod (j+List[i]) = then Exit; j := j + k; end; Prime := True; End; Vì k nhỏ nên thời gian tính toán chủ yếu phép tìm ước Trong phần tìm ước, k số ta xét l số Chú ý l = ϕ(k) số số tự nhiên không k nguyên tố với k ϕ (k ) Độ phức tạp thuật toán cỡ O( n ) k s Theo công thức Euler, k có dạng phân tích tiêu chuẩn k = ∏ piαi i =1 s 1 ϕ (k) ( − ) ϕ(k) = k ∏ , tức = ∏ (1 − ) pi pi k i =1 i =1 Do phương pháp chọn k tối ưu lấy k tích số nguyên tố Nếu chọn k n = độ phức tạp O( ), độ phức tạp thuật toán giảm đáng kể so với O( n ) Tuy nhiên, ta không thu giảm đáng kể chọn thêm số nguyên tố s K Phân tích tiêu chuẩn 2*3 30 2*3*5 210 2*3*5*7 ϕ (k) k 15 35 Trong hướng tiếp cận trên, có nguyên tắc để kiểm tra nguyên tố tìm ước không tầm thường n, trường hợp tồi (khi n số nguyên tố), ta phải xét hết số nguyên tố không n Nếu gọi π(x) số số nguyên tố không vượt x, người ta có kết tiếng sau : Chuyên đề Thuật toán Số học π ( x) lim x →∞ x = ln x Trần Quang Khải n ln n Trong thực tế, n lên tới hàng trăm chữ số thuật toán nêu rõ ràng chạy thời gian cho phép Ta cần ý chưa có thuật toán tổng quát cho kết xác thời gian chấp nhận Thuật toán xác suất Thuật toán xác xuất tiếp cận toán theo hướng khác, không theo đường tìm ước không tầm thường mà dựa vào hai tính chất khác số nguyên tố Cho p số nguyên tố, a số nguyên không chia hết cho p, ta có : ap-1 ≡ (mod p) (1) Điều cho thấy trường hợp n nguyên tố, số phép toán không a2 ≡ (mod p) ⇔ a ≡ (mod p) a ≡ -1 (mod p) (2) Hai tính chất quen thuộc số nguyên tố, ta chứng minh không khó khăn Giả sử p-1 = q2t q số nguyên dương lẻ Theo (1) (2), với số a không chia hết cho p ta có : + a q ≡ (mod p) r + a q ≡ -1 (mod p) với số nguyên r thoả ≤ r < t (*) Như vậy, số n nguyên tố phải thoả mãn điều kiện với ≤ a ≤ n-1, ngược lại tồn a không thoả mãn tính chất chắn n số nguyên tố Mặt khác, ta chứng minh rằng, n hợp số lẻ > có không (n-1) / giá trị a khoảng đến n-1 thoả mãn (*) Do đó, với số a chọn ngẫu nhiên khoảng đến n-1, xác suất a thoả mãn (*) không , k lần chọn xác suất để lần chọn thoả mãn không k Từ đó, người ta đưa thuật toán xác suất cho phép kiểm tra số n có phải nguyên tố hay không thời gian đa thức với độ xác cao Thuật toán (Rabin - Miller) mô tả sau : Function Prime(n : Integer) : Boolean; Var i, a : Integer; Begin Prime := False; Cal(n, q, t) {phân tích n-1 = q2t} For i := to k Begin a := Random(n-1) + 1; if MillerTest(n, a, q, t) = False then Exit; {Kiểm tra với sở a chọn ngẫu nhiên} End; Prime := True; End; Thủ tục Cal(n, q, t) phân tích n-1 = q2t với q số nguyên lẻ đơn giản ta nên ta không trình bày Phần quan trọng kiểm tra a có thoả mãn tính chất (*) hay không Trước hết, ta phải tính aq mod n, ta tính thực phép nhân q lần chi phí lớn (q tỉ lệ với n) Vì ta cần tính luỹ thừa modulo n nên ta có phương pháp hay : Chuyên đề Thuật toán Số học Trần Quang Khải Phương pháp bình phương liên tiếp Ý tưởng sau : phân tích q dạnh nhị phân, q có dạng tổng luỹ thừa Ta xây dựng dãy {u} sau : u0 = a uk+1 = uk2 mod n ∀ k ∈ N k Khi đó, ta dễ dàng chứng minh uk = a mod n Khi đó, aq mod n tính tích theo modulo n u k tương ứng với luỹ thừa phân tích nhị phân q Ta mô tả thủ tục sau : Function Power(a, q, n : Integer) : Integer; Var c, p2, u : Integer; Begin c := 1; u := a; p2 := 1; repeat if q and p2 then c := (c * u) mod n; p2 := p2 shl 1; u := (u * u) mod n; until p2 > q; Power := c; End; Ta dễ dàng chứng minh việc tính a q mod n thủ tục nêu phải thực không 2log2q lần phép nhân modulo n Do chi phí tính toán ( phép nhân phép chia chi phí O((logn)2) ) cỡ O(logq(logn)2) Phép kiểm tra điều kiện (*) viết sau : Function MillerTest(n, a, q, t : Integer) : Boolean; Var pre, c, i, j : Integer; Begin c := Power(a, q, n); pre := n-1; for i := to t begin if c = then begin MillerTest := (pre = n-1); Exit; end; pre := c; c := (c * c) mod n; end; MillerTest := False; End; Thủ tục MillerTest gồm phần tính a q mod n có chi phí O(logq(logn) 2) t lần thực tính bình phương modulo n có chi phí cỡ O(t(logn)2) Ta có n-1 = q2t nên độ phức tạp lần kiểm tra sở a có chí phí cỡ O((logn)3) Thuật toán thực k lần kiểm tra có chi phí O(k(logn) 3), xác suất sai không k Như vậy, độ phức tạp thuật toán tăng tuyến tính theo k, xác suất sai lầm giảm theo hàm mũ với k Chỉ cần chọn Chuyên đề Thuật toán Số học Trần Quang Khải k không lớn (k ≥ 30) xác suất sai lầm nhỏ, n trải qua phép thử với k sở a chọn ngẫu nhiên khẳng định gần chắn n số nguyên tố Thuật toán kiểm tra nguyên tố với số Fecmat số Mersenne n Số Fecmat Fn = 2 + Nhà toán học Fecmat đưa giả thiết F n số nguyên tố với n ∈ N Ta dễ dàng kiểm tra điều với n = 0, 1, 2, Tuy nhiên Euler F hợp số chia hết cho 641 Fn −1 Định lý : Fn số nguyên tố ≡ -1 (mod Fn) Số Mersenne Mp = 2p - Ta dễ thấy M p số nguyên tố p phải số nguyên tố Số Mersenne có ý nghĩa quan trọng Số học liên quan tới số hoàn chỉnh Một số nguyên dương n gọi số hoàn chỉnh tổng ước bé n n n Euler chứng minh n số hoàn chỉnh chẵn n = Mp2p-1 với Mp số nguyên tố Định lý : Cho p số nguyên tố, dãy {Ln} xác định sau : L0 = Ln+1 = Ln2 - ∀ n ∈ N Mp số nguyên tố Lp-2 ≡ (mod Mp)