canuc80k5409·10/20

Hợp Nhất Nhiều Chu Kỳ

Nộp bài trên LQDOJ

Bài 54 · Chinese Remainder Theorem

Cho đồng dư . Các mô-đun có thể có ước chung, và không nhất thiết nằm trong đoạn ; mỗi điều kiện chỉ phụ thuộc vào số dư của khi chia cho . Dữ liệu bảo đảm tồn tại ít nhất một nghiệm.

Hãy tìm nghiệm không âm nhỏ nhất của toàn bộ hệ điều kiện.

Input

  • Dòng đầu chứa . Mỗi dòng trong dòng tiếp theo chứa .

Output

  • In nghiệm không âm nhỏ nhất.

Constraints

  • .
  • ; ; được hiểu theo mô-đun .
  • Bội chung nhỏ nhất của các không vượt ; hệ luôn có nghiệm.

Scoring

  • Subtask ( số điểm): và .
  • Subtask ( số điểm): không có giới hạn bổ sung.

Example

Test 1

Input

3
6 4
8 4
9 7

Output

52

Giải thích: Hai điều kiện đầu gộp thành , nên các ứng viên đầu tiên là . Trong số đó, , vì vậy là nghiệm không âm nhỏ nhất của cả ba điều kiện.

Lời giải tóm tắt
  • Mô hình: Ta cần tìm đại diện không âm nhỏ nhất của giao n lớp đồng dư x≡b_i (mod a_i). Các mô-đun có thể có ước chung, nhưng dữ liệu bảo đảm giao không rỗng.
  • Thuật toán: Giả sử các điều kiện đã xử lý tạo thành lớp x≡r (mod M). Khi thêm x≡b_i (mod a_i), đặt
  • Thuật toán:

text g = gcd(M,a_i), diff = b_i-r. - Thuật toán: Vì hệ có nghiệm, g chia diff. Sau khi chia cho g, ta được - Thuật toán:

text t ≡ (diff/g)·(M/g)^(-1) (mod a_i/g), - Thuật toán: rồi cập nhật - Thuật toán:

text r ← r+M·t, M ← lcm(M,a_i), - Thuật toán: và chuẩn hóa r về [0,M). Các biểu thức diff, M·t và (M/g)·a_i được tính bằng __int128 trước khi đưa về kiểu 64 bit. - Chứng minh đúng đắn: Mọi số trong lớp hiện tại có dạng r+M·t. Điều kiện mới tương đương với M·t≡b_i-r (mod a_i). Sau khi chia gcd, hệ số M/g khả nghịch modulo a_i/g, nên công thức trên cho đúng toàn bộ nghiệm của phép ghép. Lớp mới có chu kỳ lcm(M,a_i) và chứa đúng giao của các điều kiện đã xử lý. - Chứng minh đúng đắn: Quy nạp theo i cho thấy lớp cuối chứa đúng mọi nghiệm của toàn hệ. Vì r luôn được chuẩn hóa về [0,M), giá trị cuối là nghiệm không âm nhỏ nhất. - Độ phức tạp: Thời gian là O(n log A), với A=max a_i; bộ nhớ phụ là O(1) ngoài dữ liệu đã đọc. - Lỗi thường gặp: Tính (M/g)·a_i bằng kiểu 64 bit rồi mới ép sang __int128. - Lỗi thường gặp: Nhân diff/g với nghịch đảo bằng kiểu quá nhỏ. - Lỗi thường gặp: Dùng Euclid mở rộng với kiểu int, làm tràn ở các mô-đun lớn.