Ước chung lớn nhất, bội chung nhỏ nhất - thuật toán Euclid
Ước chung lớn nhất (ƯCLN, tiếng Anh là gcd) và bội chung nhỏ nhất (BCNN, tiếng Anh là lcm) xuất hiện trong rất nhiều bài: rút gọn phân số, chia nhóm đều nhau, cắt hình vuông, đèn nhấp nháy cùng lúc… Thuật toán Euclid là một trong những thuật toán cổ nhất còn được dùng hằng ngày: tìm ƯCLN của hai số đến 1018 chỉ trong vài chục bước.
Ước chung lớn nhất là gì?
Phần tiêu đề “Ước chung lớn nhất là gì?”Các ước của 12 là 1, 2, 3, 4, 6, 12. Các ước của 18 là 1, 2, 3, 6, 9, 18. Các ước chung là 1, 2, 3, 6, và ước chung lớn nhất là 6.
Cách liệt kê ước như bài Ước và bội cần duyệt đến √a, tức 109 bước với a = 1018, quá chậm. Thuật toán Euclid nhanh hơn rất nhiều.
Ý tưởng của thuật toán Euclid
Phần tiêu đề “Ý tưởng của thuật toán Euclid”Nhận xét: nếu a và b cùng chia hết cho một số d thì a - b cũng chia hết cho d. Ví dụ 18 và 12 cùng chia hết cho 6, nên 18 - 12 = 6 cũng chia hết cho 6. Ngược lại, nếu b và a - b cùng chia hết cho d thì a cũng chia hết cho d. Nghĩa là a, b và b, a - b có cùng các ước chung. Vậy ƯCLN(a, b) = ƯCLN(b, a - b): thay số lớn bằng hiệu, ƯCLN không đổi.
Trừ b nhiều lần cho tới khi không trừ được nữa chính là lấy số dư a % b. Vậy:
- ƯCLN(a, b) = ƯCLN(b, a % b)
- ƯCLN(a, 0) = a (mọi số đều là ước của 0)
Lặp lại cho tới khi số thứ hai bằng 0. Chạy tay với a = 1071, b = 462:
| a | b | a % b |
|---|---|---|
| 1071 | 462 | 147 |
| 462 | 147 | 21 |
| 147 | 21 | 0 |
| 21 | 0 | dừng |
ƯCLN(1071, 462) = 21, chỉ sau 3 phép chia.
Hình ảnh dễ nhớ: có tấm bìa hình chữ nhật 1071 × 462. Cắt đi các hình vuông cạnh 462 nhiều nhất có thể, còn lại hình chữ nhật 462 × 147. Lại cắt hình vuông cạnh 147, còn 147 × 21. Cắt tiếp thì vừa hết. Hình vuông cuối cùng có cạnh 21, và tấm bìa ban đầu lát kín được bằng các hình vuông cạnh 21.
def ucln(a, b): while b != 0: a, b = b, a % b return a
print(ucln(1071, 462)) # 21
# Python có sẵn hàm:from math import gcdprint(gcd(1071, 462)) # 21#include <iostream>#include <numeric> // std::gcd (C++17)using namespace std;
long long ucln(long long a, long long b) { while (b != 0) { long long r = a % b; a = b; b = r; } return a;}
int main() { cout << ucln(1071, 462) << endl; // 21 cout << gcd(1071, 462) << endl; // 21, hàm có sẵn return 0;}Nhanh đến đâu? Cứ sau hai bước, số lớn giảm còn chưa tới một nửa. Với số đến 1018, thuật toán chỉ cần khoảng 90 bước trong trường hợp xấu nhất.
Bội chung nhỏ nhất
Phần tiêu đề “Bội chung nhỏ nhất”Các bội của 12: 12, 24, 36, 48, … Các bội của 18: 18, 36, 54, … BCNN(12, 18) = 36.
Với hai số a, b luôn có: ƯCLN × BCNN = a × b. Kiểm tra: 6 × 36 = 216 = 12 × 18. Vậy:
BCNN(a, b) = a / ƯCLN(a, b) × b
Lưu ý: phải chia trước rồi mới nhân. Viết a * b / ucln(a, b) thì với a, b
khoảng 1010, tích a × b = 1020 đã vượt quá long long của C++ (khoảng
9,2 × 1018), cho kết quả sai dù BCNN thật vẫn nhỏ.
ƯCLN và BCNN của nhiều số
Phần tiêu đề “ƯCLN và BCNN của nhiều số”Làm lần lượt từng số: ƯCLN(a, b, c) = ƯCLN(ƯCLN(a, b), c). BCNN cũng vậy.
| Số | 12 | 18 | 24 | 30 |
|---|---|---|---|---|
| ƯCLN tính đến đây | 12 | 6 | 6 | 6 |
| BCNN tính đến đây | 12 | 36 | 72 | 360 |
Mẹo: bắt đầu ƯCLN từ 0 (vì ƯCLN(0, x) = x) và BCNN từ 1, rồi gộp từng số vào.
Nguyên tố cùng nhau và phân số tối giản
Phần tiêu đề “Nguyên tố cùng nhau và phân số tối giản”- Hai số có ƯCLN bằng 1 gọi là nguyên tố cùng nhau, ví dụ 8 và 15.
- Phân số a / b tối giản khi a và b nguyên tố cùng nhau. Muốn rút gọn, chia cả tử và mẫu cho ƯCLN: 1071 / 462 = (1071 : 21) / (462 : 21) = 51 / 22.
Luyện tập
Phần tiêu đề “Luyện tập”Gồm 21 bài, chia thành 4 nhóm từ dễ đến khó. Mỗi bài có một dữ liệu kiểm tra: các bạn chạy chương trình của mình với dữ liệu đó rồi so với đáp số.
Nhóm 1. Tính ƯCLN và BCNN
Phần tiêu đề “Nhóm 1. Tính ƯCLN và BCNN”Bài 1. Ước chung lớn nhất
Phần tiêu đề “Bài 1. Ước chung lớn nhất”Nhập hai số nguyên dương a, b (a, b ≤ 1018). In ra ƯCLN(a, b).
Ví dụ: nhập 12 18 thì in ra 6.
Kiểm tra: nhập 1071 462.
Bài 2. Bội chung nhỏ nhất
Phần tiêu đề “Bài 2. Bội chung nhỏ nhất”Nhập hai số nguyên dương a, b (a, b ≤ 109). In ra BCNN(a, b).
Ví dụ: nhập 12 18 thì in ra 36.
Kiểm tra: nhập 123456 7890.
Bài 3. ƯCLN của nhiều số
Phần tiêu đề “Bài 3. ƯCLN của nhiều số”Dòng đầu là n (n ≤ 105). Dòng thứ hai có n số nguyên dương, mỗi số không quá 1018. In ra ƯCLN của n số đó.
Ví dụ:
| Nhập | In ra |
|---|---|
312 18 24 | 6 |
Kiểm tra: nhập
512 18 24 30 36Bài 4. BCNN của các số từ 1 đến n
Phần tiêu đề “Bài 4. BCNN của các số từ 1 đến n”Nhập số nguyên dương n (n ≤ 40). In ra BCNN(1, 2, …, n), tức là số nhỏ nhất chia hết cho mọi số từ 1 đến n.
Ví dụ: nhập 10 thì in ra 2520.
Kiểm tra: nhập 20.
Bài 5. Nguyên tố cùng nhau
Phần tiêu đề “Bài 5. Nguyên tố cùng nhau”Nhập hai số nguyên dương a, b (a, b ≤ 1018). In ra YES nếu a và b nguyên tố cùng nhau (ƯCLN bằng 1), ngược lại in ra NO.
Ví dụ: nhập 8 15 thì in ra YES.
Kiểm tra: nhập 391 667.
Bài 6. Số bước của thuật toán Euclid
Phần tiêu đề “Bài 6. Số bước của thuật toán Euclid”Nhập hai số nguyên dương a, b (a, b ≤ 1018). Chạy thuật toán Euclid: mỗi bước thay (a, b) bằng (b, a % b), dừng khi b = 0. In ra số bước đã thực hiện.
Ví dụ: nhập 1071 462 thì in ra 3.
Kiểm tra: nhập 832040 514229.
Nhóm 2. Phân số
Phần tiêu đề “Nhóm 2. Phân số”Bài 7. Rút gọn phân số
Phần tiêu đề “Bài 7. Rút gọn phân số”Nhập hai số nguyên dương a, b (a, b ≤ 1018). In ra phân số a / b ở dạng tối giản, theo dạng tử/mẫu.
Ví dụ: nhập 12 18 thì in ra 2/3.
Kiểm tra: nhập 1071 462.
Bài 8. Cộng hai phân số
Phần tiêu đề “Bài 8. Cộng hai phân số”Nhập bốn số nguyên dương a, b, c, d (mỗi số không quá 109). In ra a / b + c / d ở dạng tối giản tử/mẫu.
Ví dụ: nhập 1 6 1 10 thì in ra 4/15.
Kiểm tra: nhập 7 12 5 18.
Bài 9. Hai phân số bằng nhau
Phần tiêu đề “Bài 9. Hai phân số bằng nhau”Nhập bốn số nguyên dương a, b, c, d (mỗi số không quá 1018). In ra YES nếu a / b = c / d, ngược lại in ra NO.
Ví dụ: nhập 2 3 4 6 thì in ra YES.
Kiểm tra: nhập 1071 462 51 22.
Bài 10. Tổng các phân số 1/1 đến 1/n
Phần tiêu đề “Bài 10. Tổng các phân số 1/1 đến 1/n”Nhập số nguyên dương n (n ≤ 20). In ra 1/1 + 1/2 + … + 1/n ở dạng tối giản tử/mẫu.
Ví dụ: nhập 4 thì in ra 25/12.
Kiểm tra: nhập 10.
Nhóm 3. Bài toán thực tế
Phần tiêu đề “Nhóm 3. Bài toán thực tế”Bài 11. Cắt hình vuông lớn nhất
Phần tiêu đề “Bài 11. Cắt hình vuông lớn nhất”Có tấm bìa hình chữ nhật kích thước a × b (a, b ≤ 109). Cần cắt hết tấm bìa thành các hình vuông bằng nhau, cạnh là số nguyên, càng lớn càng tốt. In ra cạnh hình vuông và số hình vuông cắt được.
Ví dụ: nhập 12 18 thì in ra 6 6.
Kiểm tra: nhập 1071 462.
Bài 12. Hai đèn nhấp nháy
Phần tiêu đề “Bài 12. Hai đèn nhấp nháy”Đèn xanh cứ a giây sáng một lần, đèn đỏ cứ b giây sáng một lần (a, b ≤ 109). Lúc 0 giây cả hai cùng sáng. Hỏi sau bao nhiêu giây thì hai đèn lại cùng sáng lần tiếp theo?
Ví dụ: nhập 12 18 thì in ra 36.
Kiểm tra: nhập 1234 5678.
Bài 13. Chia nhóm nam nữ
Phần tiêu đề “Bài 13. Chia nhóm nam nữ”Lớp có a bạn nam và b bạn nữ (a, b ≤ 1018). Cô muốn chia lớp thành nhiều nhóm nhất sao cho các nhóm có số nam bằng nhau và số nữ bằng nhau. In ra số nhóm, số nam và số nữ mỗi nhóm.
Ví dụ: nhập 12 18 thì in ra 6 2 3.
Kiểm tra: nhập 1071 462.
Bài 14. Hai bánh răng
Phần tiêu đề “Bài 14. Hai bánh răng”Bánh răng A có a răng, bánh răng B có b răng ăn khớp với nhau (a, b ≤ 109). Đánh dấu một cặp răng đang chạm nhau. Hỏi bánh A và bánh B quay ít nhất bao nhiêu vòng thì cặp răng đó lại chạm nhau? In ra số vòng của A và số vòng của B.
Ví dụ: nhập 48 18 thì in ra 3 8.
Kiểm tra: nhập 1234 5678.
Bài 15. Điểm nguyên trên đoạn thẳng
Phần tiêu đề “Bài 15. Điểm nguyên trên đoạn thẳng”Nhập bốn số nguyên x1, y1, x2, y2 (giá trị tuyệt đối không quá 109, hai điểm khác nhau). Đếm số điểm có cả hai tọa độ nguyên nằm trên đoạn thẳng nối (x1, y1) với (x2, y2), kể cả hai đầu mút.
Ví dụ: nhập 0 0 4 6 thì in ra 3.
Kiểm tra: nhập 0 0 1071 462.
Bài 16. Chia hết cho a hoặc b
Phần tiêu đề “Bài 16. Chia hết cho a hoặc b”Nhập ba số nguyên dương n, a, b (n ≤ 1018, a, b ≤ 109). Đếm các số từ 1 đến n chia hết cho a hoặc chia hết cho b.
Ví dụ: nhập 20 4 6 thì in ra 7.
Kiểm tra: nhập 1000000000000000000 6 4.
Nhóm 4. Vận dụng
Phần tiêu đề “Nhóm 4. Vận dụng”Bài 17. Số ước chung của nhiều số
Phần tiêu đề “Bài 17. Số ước chung của nhiều số”Dòng đầu là n (n ≤ 105). Dòng thứ hai có n số nguyên dương, mỗi số không quá 1012. In ra số lượng ước chung của n số đó.
Ví dụ:
| Nhập | In ra |
|---|---|
212 18 | 4 |
Kiểm tra: nhập
3360 840 1260Bài 18. ƯCLN với số rất lớn
Phần tiêu đề “Bài 18. ƯCLN với số rất lớn”Dòng đầu là số nguyên dương a có không quá 105 chữ số. Dòng thứ hai là số nguyên dương b (b ≤ 109). In ra ƯCLN(a, b).
Ví dụ:
| Nhập | In ra |
|---|---|
100000000000000000000024 | 8 |
Kiểm tra: nhập
123456789123456789123456789999999999Bài 19. Tìm hai số biết ƯCLN và BCNN
Phần tiêu đề “Bài 19. Tìm hai số biết ƯCLN và BCNN”Nhập hai số nguyên dương g, l (g ≤ l ≤ 1012). Tìm hai số nguyên dương a ≤ b có ƯCLN(a, b) = g, BCNN(a, b) = l và tổng a + b nhỏ nhất. In ra a và b; nếu không có thì in ra -1.
Ví dụ: nhập 2 12 thì in ra 4 6.
Kiểm tra: nhập 6 360.
Bài 20. Đếm số nguyên tố cùng nhau với n
Phần tiêu đề “Bài 20. Đếm số nguyên tố cùng nhau với n”Nhập số nguyên dương n (n ≤ 106). Đếm các số y từ 1 đến n mà y và n nguyên tố cùng nhau.
Ví dụ: nhập 12 thì in ra 4.
Kiểm tra: nhập 2026.
Bài 21. Đoạn liên tiếp dài nhất có ƯCLN lớn hơn 1
Phần tiêu đề “Bài 21. Đoạn liên tiếp dài nhất có ƯCLN lớn hơn 1”Dòng đầu là n (n ≤ 2000). Dòng thứ hai có n số nguyên dương, mỗi số không quá 109. Tìm độ dài lớn nhất của một đoạn các số liên tiếp trong dãy mà ƯCLN của cả đoạn lớn hơn 1. Nếu không có đoạn nào thì in ra 0.
Ví dụ:
| Nhập | In ra |
|---|---|
52 4 8 3 9 | 3 |
Kiểm tra: nhập
84 6 3 9 7 14 21 5