Bỏ qua để đến nội dung

Ước và bội

Mức độ: Cơ bản

Rất nhiều bài thi học sinh giỏi hỏi về ước: đếm ước, tính tổng ước, tìm số hoàn hảo, chia nhóm đều nhau… Bài này giúp các bạn làm những việc đó nhanh hơn hàng triệu lần so với cách thử từng số, chỉ nhờ một nhận xét nhỏ: các ước luôn đi theo cặp.

Các bạn nên học trước bài Phép chia có dư và chia hết.

12 chia hết cho 3, ta nói:

  • 3 là ước của 12 (12 chia hết cho 3, ký hiệu 3 | 12).
  • 12 là bội của 3.

Trong code, “d là ước của n” chính là n % d == 0.

Các ước của 12 là 1, 2, 3, 4, 6, 12. Các bội của 3 là 0, 3, 6, 9, 12, … (vô số bội). Số 1 là ước của mọi số, và mọi số đều là ước của chính nó.

Cách dễ nghĩ nhất là thử mọi số từ 1 đến n:

n = 36
for d in range(1, n + 1):
if n % d == 0:
print(d, end=" ") # 1 2 3 4 6 9 12 18 36

Cách này đúng nhưng chậm: với n = 1012, máy phải thử 1012 số, ước lượng mất khoảng 3 tiếng.

Nhìn các ước của 36 theo từng cặp có tích bằng 36:

Ước nhỏƯớc lớnTích
13636
21836
31236
4936
6636

Mỗi khi tìm được một ước d, ta có ngay ước thứ hai là n / d. Và trong mỗi cặp, ước nhỏ không vượt quá √n (với 36 là 6): nếu cả hai số trong cặp đều lớn hơn 6 thì tích đã lớn hơn 6 × 6 = 36 rồi.

Vậy chỉ cần thử d từ 1 đến √n, mỗi lần gặp ước thì lấy luôn cả cặp:

nThử từng sốThử đến √n
106106 lần103 lần
10121012 lần (ước lượng khoảng 3 tiếng)106 lần (rất nhanh)
n = int(input())
dem = 0
d = 1
while d * d <= n: # thử d đến căn bậc hai của n
if n % d == 0:
dem += 1 # ước nhỏ d
if d != n // d:
dem += 1 # ước lớn n // d (khác d)
d += 1
print(dem) # n = 36 in ra 9

Lưu ý:

  • Khi n là số chính phương (36 = 6 × 6), cặp (6, 6) chỉ là một ước. Nếu quên kiểm tra d != n // d, chương trình sẽ đếm 6 hai lần.
  • Viết điều kiện d * d <= n, không viết d <= sqrt(n). Hàm sqrt tính bằng số thực nên có thể sai một chút với số lớn (ví dụ trả về 999999.9999 thay vì 1000000), làm thiếu mất một ước.
  • Trong C++, d phải là long long: khi n gần 1012 thì d * d vượt quá giới hạn của int.

Ước nhỏ tìm được theo thứ tự tăng dần (1, 2, 3, 4, 6), còn ước lớn theo thứ tự giảm dần (36, 18, 12, 9). Lưu hai danh sách riêng rồi ghép: ước nhỏ, sau đó ước lớn đảo ngược.

n = 36
nho, lon = [], []
d = 1
while d * d <= n:
if n % d == 0:
nho.append(d)
if d != n // d:
lon.append(n // d)
d += 1
print(*(nho + lon[::-1])) # 1 2 3 4 6 9 12 18 36

Cùng cách đó, muốn tính tổng các ước thì thay việc đếm bằng cộng d và n / d.

Số hoàn hảo là số bằng tổng các ước nhỏ hơn nó. Ví dụ 6 = 1 + 2 + 3 và 28 = 1 + 2 + 4 + 7 + 14. Đây là dạng bài rất hay gặp: tính tổng các ước bằng cách duyệt đến √n, rồi trừ đi chính n.

Các bội của k là 0, k, 2k, 3k, … Hai câu hỏi hay gặp:

  • Bội lớn nhất không vượt quá n: lấy phần nguyên rồi nhân lại, n // k * k. Ví dụ n = 2026, k = 7: 2026 // 7 = 289, 289 × 7 = 2023.
  • Bội nhỏ nhất không nhỏ hơn n: làm tròn lên rồi nhân lại, (n + k - 1) // k * k. Ví dụ trên được 2030.

Đếm số bội của k trong một đoạn thì dùng công thức b // k - (a - 1) // k đã học ở bài Phép chia có dư và chia hết.

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ập số nguyên dương n (n ≤ 1012). In ra các ước của n theo thứ tự tăng dần, cách nhau một dấu cách.

Ví dụ: nhập 12 thì in ra 1 2 3 4 6 12.

Kiểm tra: nhập 36.

Xem đáp số

1 2 3 4 6 9 12 18 36

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên dương n (n ≤ 1012). In ra số ước của n.

Ví dụ: nhập 36 thì in ra 9.

Kiểm tra: nhập 1000000000000.

Xem đáp số

169

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên dương n (n ≤ 1012). In ra tổng tất cả các ước của n (kể cả 1 và n).

Ví dụ: nhập 12 thì in ra 28.

Kiểm tra: nhập 360.

Xem đáp số

1170

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên n (2 ≤ n ≤ 1012). In ra ước lớn nhất của n mà nhỏ hơn n.

Ví dụ: nhập 12 thì in ra 6.

Kiểm tra: nhập 1001.

Xem đáp số

143

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên dương n (n ≤ 1012). In ra số ước lẻ của n.

Ví dụ: nhập 12 thì in ra 2.

Kiểm tra: nhập 360.

Xem đáp số

6

Hướng dẫn giải chi tiết: liên hệ tác giả.

Số hoàn hảo là số bằng tổng các ước nhỏ hơn nó, ví dụ 6 = 1 + 2 + 3. Nhập số nguyên dương n (n ≤ 1012), in ra YES nếu n là số hoàn hảo, ngược lại in ra NO.

Ví dụ: nhập 28 thì in ra YES.

Kiểm tra: nhập 8128.

Xem đáp số

YES

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên dương n (n ≤ 105). In ra các số hoàn hảo không vượt quá n, theo thứ tự tăng dần, cách nhau một dấu cách. Nếu không có số nào thì in ra 0.

Ví dụ: nhập 100 thì in ra 6 28.

Kiểm tra: nhập 10000.

Xem đáp số

6 28 496 8128

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập hai số nguyên dương n, k (n, k ≤ 1012). In ra bội nhỏ nhất của k mà lớn hơn hoặc bằng n.

Ví dụ: nhập 20 7 thì in ra 21.

Kiểm tra: nhập 2026 7.

Xem đáp số

2030

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập hai số nguyên dương n, k (k ≤ n ≤ 1018). In ra bội lớn nhất của k mà nhỏ hơn hoặc bằng n.

Ví dụ: nhập 20 7 thì in ra 14.

Kiểm tra: nhập 2026 7.

Xem đáp số

2023

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập hai số nguyên dương n, k (k ≤ n ≤ 1018). In ra bội của k gần n nhất. Nếu có hai bội cách n bằng nhau thì in ra bội nhỏ hơn.

Ví dụ: nhập 20 8 thì in ra 16.

Kiểm tra: nhập 2026 8.

Xem đáp số

2024

Hướng dẫn giải chi tiết: liên hệ tác giả.

Bài 11. Bội của a nhưng không là bội của b

Phần tiêu đề “Bài 11. Bội của a nhưng không là bội của b”

Nhập ba số nguyên dương n, a, b (n ≤ 1018, b là bội của a). Đếm xem từ 1 đến n có bao nhiêu số chia hết cho a nhưng không chia hết cho b.

Ví dụ: nhập 20 2 4 thì in ra 5.

Kiểm tra: nhập 1000 3 9.

Xem đáp số

222

Hướng dẫn giải chi tiết: liên hệ tác giả.

Có n bóng đèn đánh số từ 1 đến n, ban đầu đều tắt. Có n lượt bấm: ở lượt thứ i, người ta bấm công tắc của mọi bóng có số thứ tự chia hết cho i (bóng đang tắt thì sáng, đang sáng thì tắt). Nhập n (n ≤ 1018), in ra số bóng đèn sáng sau n lượt.

Ví dụ: nhập 10 thì in ra 3.

Kiểm tra: nhập 2026.

Xem đáp số

45

Hướng dẫn giải chi tiết: liên hệ tác giả.

Lớp có n học sinh (n ≤ 1012). Cô muốn chia lớp thành các nhóm có số người bằng nhau, mỗi nhóm ít nhất 2 người và có ít nhất 2 nhóm. In ra số cách chia.

Ví dụ: nhập 12 thì in ra 4.

Kiểm tra: nhập 36.

Xem đáp số

7

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên dương n (n ≤ 1012). Xét các hình chữ nhật có hai cạnh là số nguyên dương và diện tích đúng bằng n. In ra chu vi nhỏ nhất của các hình chữ nhật đó.

Ví dụ: nhập 12 thì in ra 14.

Kiểm tra: nhập 1000.

Xem đáp số

130

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên dương n (n ≤ 1012). Đếm số cặp số nguyên dương (a, b) với a ≤ b và a × b = n.

Ví dụ: nhập 12 thì in ra 3.

Kiểm tra: nhập 360.

Xem đáp số

12

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên dương n (n ≤ 1018). In ra ước lẻ lớn nhất của n.

Ví dụ: nhập 24 thì in ra 3.

Kiểm tra: nhập 2074624.

Xem đáp số

1013

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập hai số nguyên dương a, b (a, b ≤ 1012). In ra các ước chung của a và b theo thứ tự tăng dần, cách nhau một dấu cách.

Ví dụ: nhập 12 18 thì in ra 1 2 3 6.

Kiểm tra: nhập 36 48.

Xem đáp số

1 2 3 4 6 12

Hướng dẫn giải chi tiết: liên hệ tác giả.

Gọi d(x) là số ước của x. Nhập số nguyên dương n (n ≤ 107), in ra d(1) + d(2) + … + d(n).

Ví dụ: nhập 10 thì in ra 27.

Kiểm tra: nhập 1000.

Xem đáp số

7069

Hướng dẫn giải chi tiết: liên hệ tác giả.

Gọi σ(x) là tổng các ước của x. Nhập số nguyên dương n (n ≤ 107), in ra σ(1) + σ(2) + … + σ(n).

Ví dụ: nhập 4 thì in ra 15.

Kiểm tra: nhập 1000.

Xem đáp số

823081

Hướng dẫn giải chi tiết: liên hệ tác giả.

Nhập số nguyên dương n (n ≤ 106). In ra số trong đoạn từ 1 đến n có nhiều ước nhất và số ước của nó. Nếu có nhiều số cùng nhiều ước nhất thì chọn số nhỏ nhất.

Ví dụ: nhập 10 thì in ra 6 4.

Kiểm tra: nhập 1000.

Xem đáp số

840 32

Hướng dẫn giải chi tiết: liên hệ tác giả.

Số dư thừa là số có tổng các ước nhỏ hơn nó lớn hơn chính nó, ví dụ 12 (1 + 2 + 3 + 4 + 6 = 16 > 12). Nhập số nguyên dương n (n ≤ 106), đếm số dư thừa không vượt quá n.

Ví dụ: nhập 20 thì in ra 3.

Kiểm tra: nhập 1000.

Xem đáp số

246

Hướng dẫn giải chi tiết: liên hệ tác giả.