Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Hướng tiếp cận
Đặt và là tích tiền tố modular. Khi đó
Vì là số nguyên tố và , mọi trong , do đó nghịch đảo tồn tại.
Nhận xét quan trọng
Phép chia thông thường không phù hợp: với tích tiền tố đã lấy modulo, trong không cho ra kết quả đúng. Ta phải dùng nghịch đảo modular.
Theo định lý nhỏ Fermat: với mọi không chia hết cho .
Thuật toán
Có hai cách triển khai:
Cách 1 — Tính nghịch đảo trên từng truy vấn. Với mỗi truy vấn , tính bằng luỹ thừa nhanh, sau đó đáp án là . Mỗi truy vấn mất .
Cách 2 — Tính trước nghịch đảo (khuyên dùng).
- Tính tích tiền tố .
- Tính nghịch đảo của tích tiền tố cuối: .
- Suy ngược: .
Khi đó mỗi truy vấn được trả lời trong :
Độ phức tạp
- Cách 1: .
- Cách 2: — chỉ một phép luỹ thừa nhanh duy nhất.
Bộ nhớ: .
Lưu ý cài đặt. Trong C++, dùng long long cho phép nhân vì có thể đạt , và tích hai số như vậy cỡ vẫn nằm trong long long nhưng tràn nếu dùng int.
Bình luận