Greatest Common Divisor
Bạn nhận được hai số nguyên dương a và b. Hãy trả về ước chung lớn nhất của chúng, tức là số nguyên lớn nhất chia hết cả hai số.
Ví dụ, các số chia hết cả 8 và 12 là 1, 2 và 4, vậy đáp án là 4.
Hàm
- ainteger
- số nguyên dương đầu tiên
- binteger
- số nguyên dương thứ hai
- Trả vềinteger
- số nguyên lớn nhất chia hết cả a và b
Ràng buộc
1 ≤ a ≤ 1091 ≤ b ≤ 109
Ví dụ
- Đầu vào
- a = 12b = 18
- Đầu ra
- 6
- Giải thích
- Các ước số của
12là 1, 2, 3, 4, 6 và 12; các ước số của18là 1, 2, 3, 6, 9 và 18. Số lớn nhất có trong cả hai danh sách là6.
- Đầu vào
- a = 17b = 5
- Đầu ra
- 1
- Giải thích
17và5đều là số nguyên tố và khác nhau, nên ước số duy nhất mà chúng có chung là1.
- Đầu vào
- a = 42b = 42
- Đầu ra
- 42
- Giải thích
- Một số chia hết cho chính nó, và không có số nào lớn hơn
42có thể chia hết cho42, nên ước chung lớn nhất của42và42là42.
Câu hỏi mở rộng
Bạn có thể mở rộng thuật toán Euclid để trả về cả hai số nguyên x và y sao cho a × x + b × y = gcd(a, b) không?
Gợi ý
Mở từng gợi ý một. Mỗi gợi ý tiết lộ thêm một chút.
Ước chung của
avàbkhông bao giờ lớn hơn số nhỏ hơn trong hai số đó. Bạn sẽ phải thử bao nhiêu ứng viên với hai số gần10^9?Mọi số chia hết cả
avàbcũng chia hếta % b. Vì vậy,gcd(a, b)bằnggcd(b, a % b), và cặp thứ hai nhỏ hơn.Tiếp tục thay cặp
(a, b)bằng(b, a % b). Khi số thứ hai bằng0, số thứ nhất là đáp án.
Lời giải
Thử từng ứng viên một sẽ hiệu quả với các số nhỏ, nhưng hai số gần 10^9 không có thừa số chung buộc bạn phải thử đến một tỷ lần. Quy tắc Euclid gcd(a, b) = gcd(b, a % b) thu nhỏ cặp số nhanh đến mức không có cặp số nào đến 10^9 cần quá 43 bước.
Đếm ngược từ số nhỏ hơn
Đúng, nhưng không chạy xong với các test lớn nhất
Ý tưởng
Ước chung không thể lớn hơn số nhỏ hơn. Bắt đầu với d bằng min(a, b) rồi giảm đi một đơn vị cho đến khi nó chia hết cả hai số. Vì bạn bắt đầu từ số lớn nhất, số đầu tiên tìm được chính là ước chung lớn nhất, và vòng lặp luôn dừng ở 1. Với 12 và 18, bạn thử từ 12 giảm xuống 7 rồi dừng ở 6.
Mỗi ứng viên cần thử một lần. Với hai số nguyên tố 999999937 và 999999929, kết quả là 1, nên vòng lặp chạy gần 10^9 lần.
Thuật toán
- Đặt
dbằng giá trị nhỏ hơn trongavàb. - Trong khi
a % dhoặcb % dkhác0, hãy trừ 1 khỏid. - Trả về
d.
def gcd(a, b):
d = min(a, b)
while a % d != 0 or b % d != 0:
d -= 1
return dThuật toán Euclid
Ý tưởng
Viết a = q × b + r với r = a % b. Một số chia hết cho a và b cũng chia hết cho r = a - q × b, và một số chia hết cho b và r cũng chia hết cho a = q × b + r. Vì vậy, (a, b) và (b, r) có cùng các ước chung, và có cùng ước chung lớn nhất.
Lặp lại cho đến khi b bằng 0. Mọi số đều chia hết cho 0, vì vậy gcd(a, 0) = a. Với 12 và 18, các cặp lần lượt là (12, 18), (18, 12), (12, 6), (6, 0), và đáp án là 6. Khi a nhỏ hơn, bước đầu tiên sẽ đổi chỗ hai số, nên bạn không cần sắp xếp.
Cứ sau hai bước, số lớn hơn giảm ít nhất một nửa, vì vậy vòng lặp chạy O(log(min(a, b))) lần.
Thuật toán
- Khi
bkhác0, hãy tínhr = a % b. - Đặt
a = bvàb = r. - Khi
bđạt0, trả vềa.
def gcd(a, b):
# gcd(a, b) == gcd(b, a % b), and gcd(a, 0) == a.
while b != 0:
a, b = b, a % b
return a
Lỗi thường gặp và trường hợp biên
- Cập nhật sai thứ tự.
a = brồi đếnb = a % bsẽ tínhb % b, kết quả luôn là0. Hãy lưu số dư (remainder) trước hoặc gán cả hai giá trị cùng lúc. - Trả về
bkhi vòng lặp (loop) kết thúc. Lúc đó,bbằng0. - Dừng đếm ngược ở
2. Khi đó, các cặp nguyên tố cùng nhau như17và5sẽ không tìm được đáp án. - Dùng phép trừ lặp lại thay vì phép lấy số dư. Khi đó,
gcd(10^9, 1)cần một tỷ phép trừ, còn một phép%là đủ.
Câu hỏi thường gặp3
Độ phức tạp thời gian của thuật toán Euclid là gì?
O(log(min(a, b))) bước và không gian O(1). Đầu vào khiến thuật toán chạy chậm nhất là các số Fibonacci liên tiếp: 701408733 và 433494437 cần 42 bước, hoặc 43 bước nếu số nhỏ hơn đứng trước, nhiều nhất trong mọi cặp số có giá trị đến 10^9.
Sự khác nhau giữa GCD và LCM là gì?
Ước chung lớn nhất là số lớn nhất chia hết cho cả hai đầu vào; bội chung nhỏ nhất là số nhỏ nhất chia hết cho cả hai đầu vào. Chúng liên hệ với nhau qua gcd(a, b) × lcm(a, b) = a × b, vì vậy bội chung nhỏ nhất là a / gcd(a, b) × b.
Ước chung lớn nhất của hai số nguyên tố cùng nhau là bao nhiêu?
Đó là 1: hai số nguyên tố cùng nhau khi và chỉ khi chúng không có thừa số nguyên tố chung. Hai số nguyên tố khác nhau luôn nguyên tố cùng nhau, và hai số nguyên liên tiếp như 8 và 9 cũng vậy.
Bài tập tương tự
Các bài tập dùng cùng ý tưởng. Giải hai hoặc ba bài là bạn sẽ nhớ được mẫu này.
def gcd(a, b):
# Viết code ở đâyKiểm thử #1
Kiểm thử #2
Kiểm thử #3
Đối số
a = 12 b = 18
Đầu ra mong đợi
6