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

Định lý số dư Trung Hoa

Mức độ: Nâng cao

Bài toán cổ Hàn Tín điểm binh: cho quân xếp hàng 3 thì thừa 2 người, xếp hàng 5 thì thừa 3 người, xếp hàng 7 thì thừa 2 người. Hỏi có ít nhất bao nhiêu quân?

Viết theo đồng dư, cần tìm x sao cho

  • x ≡ 2 (mod 3)
  • x ≡ 3 (mod 5)
  • x ≡ 2 (mod 7)

Định lý số dư Trung Hoa nói rằng: nếu các modulo đôi một nguyên tố cùng nhau thì hệ luôn có nghiệm, và các nghiệm cách nhau đúng tích các modulo (ở đây 3 × 5 × 7 = 105). Đáp số là 23 (rồi 128, 233, …).

Các bạn cần nắm vững bài Đồng dư và bài Thuật toán Euclid mở rộng trước khi học bài này.

Chỉ cần thử các số thỏa mãn đồng dư có modulo lớn nhất: 2, 9, 16, 23, … (thỏa mãn x ≡ 2 (mod 7)), rồi kiểm tra hai đồng dư còn lại.

xx % 3x % 5
222
904
1611
2323

Cách này cần thử tới m1 × m2 × … chia cho modulo lớn nhất số, chỉ dùng được khi các modulo nhỏ.

Ghép hai đồng dư đầu thành một đồng dư, rồi ghép tiếp với đồng dư thứ ba, cứ thế đến hết.

Ghép x ≡ r1 (mod m1) với x ≡ r2 (mod m2): từ đồng dư thứ nhất, x = r1 + m1 × t. Thay vào đồng dư thứ hai:

m1 × t ≡ r2 - r1 (mod m2)

Đây là phương trình đồng dư đã giải ở bài Euclid mở rộng. Đặt g = ƯCLN(m1, m2):

  • Nếu r2 - r1 không chia hết cho g: hệ vô nghiệm.
  • Ngược lại: t = (r2 - r1) / g × p % (m2 / g), với p là hệ số Bézout của m1 (m1 × p + m2 × q = g). Hai đồng dư gộp thành x ≡ r1 + m1 × t (mod BCNN(m1, m2)).

Cách này dùng được cả khi các modulo không nguyên tố cùng nhau. Chạy với bài Hàn Tín:

GhépgtKết quả
x ≡ 2 (mod 3) với x ≡ 3 (mod 5)12x ≡ 2 + 3 × 2 = 8 (mod 15)
x ≡ 8 (mod 15) với x ≡ 2 (mod 7)11x ≡ 8 + 15 × 1 = 23 (mod 105)
def euclid_mo_rong(a, b):
if b == 0:
return a, 1, 0
g, x1, y1 = euclid_mo_rong(b, a % b)
return g, y1, x1 - (a // b) * y1
def ghep(r1, m1, r2, m2):
"""Gộp x ≡ r1 (mod m1) và x ≡ r2 (mod m2) thành (r, m); None nếu vô nghiệm."""
g, p, _ = euclid_mo_rong(m1, m2)
if (r2 - r1) % g != 0:
return None
m2g = m2 // g
t = (r2 - r1) // g * p % m2g
m = m1 * m2g # BCNN(m1, m2)
return (r1 + m1 * t) % m, m
r, m = 0, 1 # x ≡ 0 (mod 1): mọi số
for mi, ri in [(3, 2), (5, 3), (7, 2)]:
r, m = ghep(r, m, ri, mi)
print(r, m) # 23 105

Lưu ý về tràn số: modulo sau khi gộp có thể tới 1018, và m1 × t có thể vượt long long. Trong C++ phải nhân bằng __int128 như hàm trên. Python không bị tràn số.

Lưu ý về điểm bắt đầu: gộp bắt đầu từ x ≡ 0 (mod 1), tức “mọi số nguyên”. Như vậy không cần xử lý riêng đồng dư đầu tiên.

x ≡ 5 (mod 12) và x ≡ 11 (mod 18): g = 6, và 11 - 5 = 6 chia hết cho 6, nên có nghiệm: x ≡ 29 (mod 36). Thử lại: 29 = 2 × 12 + 5 = 18 + 11.

x ≡ 1 (mod 4) và x ≡ 2 (mod 6): g = 2, 2 - 1 = 1 không chia hết cho 2, vô nghiệm. Dễ thấy vì đồng dư thứ nhất bắt x lẻ, đồng dư thứ hai bắt x chẵn.

Công thức khi các modulo nguyên tố cùng nhau

Phần tiêu đề “Công thức khi các modulo nguyên tố cùng nhau”

Khi các modulo đôi một nguyên tố cùng nhau, đặt M = m1 × m2 × … × mk và Mi = M / mi. Gọi yi là nghịch đảo của Mi theo modulo mi. Khi đó

x = (r1 × M1 × y1 + … + rk × Mk × yk) % M

Mỗi số hạng ri × Mi × yi chia mi dư ri và chia hết cho mọi modulo khác. Với bài Hàn Tín: M = 105, ba số hạng là 2 × 35 × 2, 3 × 21 × 1, 2 × 15 × 1, tổng 233 ≡ 23 (mod 105).

Công thức đẹp nhưng chỉ dùng được khi các modulo nguyên tố cùng nhau. Khi lập trình, cách ghép từng cặp an toàn hơn.

Gồm 20 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 bốn số r1, m1, r2, m2 (1 ≤ m1, m2 ≤ 1000, 0 ≤ r1 nhỏ hơn m1, 0 ≤ r2 nhỏ hơn m2). In ra số x ≥ 0 nhỏ nhất sao cho x chia m1 dư r1 và chia m2 dư r2, hoặc -1 nếu không có.

Ví dụ: nhập 2 3 3 5 thì in ra 8.

Kiểm tra: nhập 17 101 45 997.

Xem đáp số

40922

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

Nhập r1, m1, r2, m2 (1 ≤ m1, m2 ≤ 109, ƯCLN(m1, m2) = 1, 0 ≤ ri nhỏ hơn mi). In ra số x ≥ 0 nhỏ nhất thỏa mãn x ≡ r1 (mod m1) và x ≡ r2 (mod m2).

Ví dụ: nhập 2 3 3 5 thì in ra 8.

Kiểm tra: nhập 123456 999999937 654321 1000000007.

Xem đáp số

214278118500601140

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

Nhập r1, m1, r2, m2 (1 ≤ m1, m2 ≤ 109, 0 ≤ ri nhỏ hơn mi). In ra số x ≥ 0 nhỏ nhất thỏa mãn hai đồng dư, hoặc -1 nếu vô nghiệm. Các modulo không nhất thiết nguyên tố cùng nhau.

Ví dụ: nhập 5 12 11 18 thì in ra 29.

Kiểm tra: nhập 123456789 999999000 999789 1000000.

Xem đáp số

457122999789

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

Nhập r1, m1, r2, m2, N (1 ≤ mi ≤ 109, 0 ≤ ri nhỏ hơn mi, 1 ≤ N ≤ 1018). Có bao nhiêu số x từ 1 đến N thỏa mãn x ≡ r1 (mod m1) và x ≡ r2 (mod m2)?

Ví dụ: nhập 2 3 3 5 100 thì in ra 7.

Kiểm tra: nhập 5 12 11 18 1000000.

Xem đáp số

27777

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

Nhập r1, m1, r2, m2, k (1 ≤ mi ≤ 106, 0 ≤ ri nhỏ hơn mi, 1 ≤ k ≤ 106). In ra số nguyên dương thứ k (theo thứ tự tăng dần) thỏa mãn hai đồng dư, hoặc -1 nếu không có số nào.

Ví dụ: nhập 2 3 3 5 2 thì in ra 23.

Kiểm tra: nhập 5 12 11 18 1000.

Xem đáp số

35993

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

Có ba dòng, mỗi dòng hai số m, r (1 ≤ m ≤ 100, 0 ≤ r nhỏ hơn m): xếp quân thành hàng m thì thừa r người. In ra số quân ít nhất có thể (một số ≥ 0), hoặc -1 nếu không thể xảy ra.

Ví dụ:

NhậpIn ra
3 2
5 3
7 2
23

Kiểm tra: nhập

7 3
11 5
13 9
Xem đáp số

269

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

Dòng đầu là n (1 ≤ n ≤ 20). n dòng sau, mỗi dòng hai số mi, ri (mi ≥ 1, 0 ≤ ri nhỏ hơn mi), các mi đôi một nguyên tố cùng nhau và tích của chúng không vượt quá 1018. In ra số x ≥ 0 nhỏ nhất thỏa mãn mọi đồng dư.

Ví dụ:

NhậpIn ra
3
3 2
5 3
7 2
23

Kiểm tra: nhập

5
1000003 17
999983 5
101 100
97 3
89 88
Xem đáp số

469650624774647498

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

Dòng đầu là n (1 ≤ n ≤ 105). n dòng sau, mỗi dòng hai số mi, ri (1 ≤ mi ≤ 109, 0 ≤ ri nhỏ hơn mi). Biết BCNN của mọi mi không vượt quá 1018. In ra số x ≥ 0 nhỏ nhất thỏa mãn mọi đồng dư, hoặc -1 nếu vô nghiệm.

Ví dụ:

NhậpIn ra
3
4 3
6 5
9 8
35

Kiểm tra: nhập

6
12 9
18 9
30 9
45 9
1000 789
999 369
Xem đáp số

579789

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

Dòng đầu là n, L, R (1 ≤ n ≤ 105, 1 ≤ L ≤ R ≤ 1018). n dòng sau, mỗi dòng hai số mi, ri như bài 8. Có bao nhiêu số x từ L đến R thỏa mãn mọi đồng dư?

Ví dụ:

NhậpIn ra
2 1 100
3 2
5 3
7

Kiểm tra: nhập

3 1 1000000000000
6 1
10 7
15 7
Xem đáp số

33333333334

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

Dòng đầu là n (1 ≤ n ≤ 10). n dòng sau, mỗi dòng ba số ai, bi, mi (0 ≤ ai, bi nhỏ hơn mi, 1 ≤ mi ≤ 106), nghĩa là ai × x ≡ bi (mod mi). Biết BCNN của mọi mi không vượt quá 1018. In ra số x ≥ 0 nhỏ nhất thỏa mãn cả hệ, hoặc -1.

Ví dụ:

NhậpIn ra
2
2 1 3
3 4 5
8

Kiểm tra: nhập

3
6 4 10
4 3 7
5 2 9
Xem đáp số

139

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

Ba ngọn đèn nhấp nháy. Đèn thứ i lóe sáng lần đầu ở giây ti, sau đó cứ pi giây lại lóe sáng một lần. Có ba dòng, mỗi dòng hai số ti, pi (0 ≤ ti ≤ 106, 1 ≤ pi ≤ 106). In ra giây đầu tiên cả ba đèn cùng lóe sáng, hoặc -1 nếu không bao giờ.

Ví dụ:

NhậpIn ra
2 3
3 5
2 7
23

Kiểm tra: nhập

100 12
4 18
40 45
Xem đáp số

220

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

Năm âm lịch được gọi bằng một can (Giáp, Ất, Bính, Đinh, Mậu, Kỷ, Canh, Tân, Nhâm, Quý, lặp lại sau 10 năm) và một chi (Tý, Sửu, Dần, Mão, Thìn, Tỵ, Ngọ, Mùi, Thân, Dậu, Tuất, Hợi, lặp lại sau 12 năm). Năm 1984 là năm Giáp Tý, năm 1985 là Ất Sửu, và cứ thế. Nhập tên can, tên chi và một năm L (1 ≤ L ≤ 109). In ra năm nhỏ nhất từ L trở đi có can chi đó, hoặc -1 nếu không có năm nào như vậy.

Ví dụ: nhập Bính Ngọ 2000 thì in ra 2026.

Kiểm tra: nhập Giáp Tý 2026.

Xem đáp số

2044

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

Nhập ba số nguyên dương a, b, c (a, b, c ≤ 106). Tìm số nguyên dương x nhỏ nhất sao cho x chia hết cho a, x + 1 chia hết cho b và x + 2 chia hết cho c. In ra -1 nếu không có.

Ví dụ: nhập 2 3 5 thì in ra 8.

Kiểm tra: nhập 7 11 13.

Xem đáp số

791

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

Nhập r1, m1, r2, m2, N (1 ≤ mi ≤ 109, 0 ≤ ri nhỏ hơn mi, 1 ≤ N ≤ 1018). Có bao nhiêu số x từ 1 đến N thỏa mãn ít nhất một trong hai đồng dư x ≡ r1 (mod m1), x ≡ r2 (mod m2)?

Ví dụ: nhập 2 3 3 5 30 thì in ra 14.

Kiểm tra: nhập 5 12 11 18 1000000.

Xem đáp số

111111

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

Dãy A gồm n số A0, …, An-1 được viết lặp lại mãi: A0, A1, …, An-1, A0, A1, … Dãy B gồm m số cũng được viết lặp lại như vậy. Dòng đầu là n, m (1 ≤ n, m ≤ 300), hai dòng sau là các số của A và B (không quá 109). Tìm vị trí i ≥ 0 nhỏ nhất mà phần tử thứ i của hai dãy bằng nhau (vị trí đầu tiên là 0). In ra -1 nếu không có.

Ví dụ:

NhậpIn ra
3 4
1 2 3
4 5 6 3
11

Kiểm tra: nhập

6 8
1 3 5 5 1 2
8 2 8 7 3 8 7 5
Xem đáp số

15

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

Dòng đầu là n, L, R (1 ≤ n ≤ 10, 1 ≤ L ≤ R ≤ 1012). n dòng sau có dạng m thừa r (xếp hàng m thì thừa r người) hoặc m thiếu r (xếp hàng m thì hàng cuối thiếu r người), với 2 ≤ m ≤ 1000, 0 ≤ r nhỏ hơn m. In ra số quân nhỏ nhất trong đoạn từ L đến R, hoặc -1 nếu không có.

Ví dụ:

NhậpIn ra
3 1000 1100
3 thừa 2
5 thừa 3
7 thiếu 5
1073

Kiểm tra: nhập

4 2000 5000
5 thiếu 1
6 thừa 5
7 thiếu 3
11 thừa 1
Xem đáp số

2069

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

Dòng đầu là n, m (1 ≤ n ≤ 105, 2 ≤ m ≤ 1018). Dòng thứ hai có n số nguyên dương không quá 1018. In ra tích của n số chia lấy dư cho m.

Ví dụ:

NhậpIn ra
3 1000000000000000000
1000000000 1000000000 7
0

Kiểm tra: nhập

6 999999999999999989
376625161664043530 808129322734854035 227670544625192561 618416730735372602 889956528077943303 883282125704228471
Xem đáp số

214709742004860396

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

Bài 18. Lũy thừa theo modulo là tích hai số nguyên tố

Phần tiêu đề “Bài 18. Lũy thừa theo modulo là tích hai số nguyên tố”

Gọi P = 1000000007 × 998244353 (cả hai đều là số nguyên tố). Nhập n (0 ≤ n ≤ 1018). In ra 2n chia lấy dư cho P.

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

Kiểm tra: nhập 1000000000000000000.

Xem đáp số

860803782745102692

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

Bài 19. Nghiệm rất lớn: thuật toán Garner

Phần tiêu đề “Bài 19. Nghiệm rất lớn: thuật toán Garner”

Dòng đầu là n (1 ≤ n ≤ 1000). n dòng sau, mỗi dòng hai số mi, ri (2 ≤ mi ≤ 2 × 109, 0 ≤ ri nhỏ hơn mi), các mi đôi một nguyên tố cùng nhau. Gọi x là số ≥ 0 nhỏ nhất thỏa mãn mọi đồng dư (x có thể có hàng nghìn chữ số). In ra x chia lấy dư cho 109 + 7.

Ví dụ:

NhậpIn ra
3
3 2
5 3
7 2
23

Kiểm tra: nhập

5
998244353 337405251
1000000009 225727008
999999937 426508939
754974721 270060143
167772161 93323692
Xem đáp số

782075277

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

Dòng đầu là n (1 ≤ n ≤ 105). n dòng sau, mỗi dòng hai số mi, ri (1 ≤ mi ≤ 106, 0 ≤ ri nhỏ hơn mi). Hệ đồng dư có nghiệm không? In ra CÓ hoặc KHÔNG. (BCNN của các mi có thể rất lớn.)

Ví dụ:

NhậpIn ra
3
4 1
6 3
9 7
KHÔNG

Kiểm tra: nhập

40
974461 251621
373962 132656
844248 837032
394627 82308
782208 55424
538537 302608
668697 382331
80029 13131
758239 249294
356931 9722
94022 24830
584531 126186
564203 464687
306313 205644
301574 56796
479670 420404
147734 106242
919052 86752
676118 390258
738173 386703
751217 622578
605474 494640
324010 186334
25943 7808
888978 303518
745395 467024
386763 175382
381203 228338
483471 217262
442729 321984
95091 68648
418146 194732
934250 682084
614171 25994
581383 557960
522670 450494
909353 158606
122106 260
446111 37053
530957 106384
Xem đáp số

CÓ

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