Editorial for Bedao Mini Contest 13 - VIRUS


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Author: bedao

Subtask 1

Bruteforce ~O(n \times t)~. Ta đánh số lại ~n~ người từ ~0~ đến ~n-1~ theo chiều kim đồng hồ.

Gọi ~tp_{i, j}~ là trạng thái của người thứ ~i~ ở giây thứ ~j~. ~tp_{i, j}~ = ~0~ nếu ở giây thứ ~j~, người thứ ~i~ không bị nhiễm virus, ~tp_{i, j}~ = ~1~ nếu ở giây thứ ~j~, người thứ ~i~ bị nhiễm virus. Ta chuyển trạng thái của ~n~ người này từ giây thứ ~j~ sang giây thứ ~j+1~ bằng cách nếu ~tp_{i, j}~ = ~1~, ta cập nhật ~tp_{(i-k+n)\%n,j+1} := 1~ và ~tp_{(i+k)\%n,j+1} := 1~.

Đáp án bằng tổng số lượng người có ~tp_{i, t}~ = ~1~.

Subtask} 2

Ta nhận thấy sau mỗi lần phân tách ra làm 2, ta xoay bàn tròn theo chiều kim đồng hồ k đơn vị thì ta thấy bản chất sau mỗi giây, virus mới được sinh ra sẽ cách virus cũ ~2 \times k~ đơn vị theo chiều kim đồng hồ. Vì virus sau mỗi giây sinh ra một bản sao nên số virus sau ~t~ giây nhiều nhất sẽ là ~t~. Đương nhiên số virus tồn tại sẽ không thể là vô hạn nên ta cần tìm cận trên của số virus. Cận trên của số virus ta có thể đưa về bài toán:

Cho một chu trình đơn gồm ~n~ đỉnh đánh số từ ~0~, đánh dấu đỉnh ~0~, từ ~i~ đang được đánh dấu, ta đánh dấu thêm đỉnh ~(i+k)\%n~ trên đồ thị, hỏi sau khi lặp lại vô hạn lần hành động trên, sẽ có bao nhiêu đỉnh được đánh dấu.

Ta có thể thấy các đỉnh bình đẳng với nhau, nghĩa là nếu khoảng cách (tính cả 2 phía) giữa 2 đỉnh bất kỳ tồn tại (gọi là ~x~) thì với một đỉnh đã được đánh dấu bất kỳ ~i~ thì ta luôn có thể đánh dấu đỉnh ~(i \pm x)\%n~. Cũng vì tất cả các đỉnh bình đẳng với nhau nên trạng thái ko thể có đỉnh mới được đánh dấu là khi tất cả các đỉnh đó cách đều nhau, nghĩa là khoảng cách giữa 2 đỉnh bất kỳ là gần nhau nhất có thể.

Ta gọi hàm g(x, y) với x khoảng cách nhỏ nhất giữa 2 đỉnh khác nhau bất kỳ, y là khoảng cách nhỏ nhì (khác k/c nhỏ nhất) của 2 đỉnh khác nhau bất kỳ (~y>x~). Ta dễ thấy: ~g(x, y) = g(min(x, y-x), max(x, y-x))~, ~g(x, 2 \times x) = x~. Bản chất g(x, y) là hàm gcd(x, y). Vì thế khoảng cách nhỏ nhất giữa các đỉnh với nhau là ~gcd(n, k)~ và số đỉnh được đánh dấu là ~n / gcd(n, k)~.

Vậy kết quả của sub ~2~ là min(~t+1~, ~n/gcd(n, 2 \times k~)). Độ phức tạp thuật toán: Độ phức tạp của hàm gcd.

Subtask 3

Với cách xoay bảng tương tự subtask 2, có thể thấy đây là bài toán cho trước ~m~ điểm trên đồ thị và yêu cầu ta phải đi đánh dấu điểm cách ~2 \times k~ đơn vị trong ~t~ giây. Từ cách chứng minh của bài trên, ta nhận ra trên bàn tròn của ta có đúng ~gcd(n, 2 \times k)~ thành phần liên thông (nếu xét ~t = \inf~), đỉnh ~i~ thuộc thành phần liên thông thứ ~i \% gcd(n, 2 \times k)~. Với nhận xét trên ta có thể tách vòng tròn của mình ra thành ~gcd(n, 2 \times k)~ phần độc lập và giải quyết nó riêng lẻ với nhau, mỗi phần sẽ có ~n/gcd~ đỉnh và độ lớn bước nhảy là ~2 \times k/gcd~. Từ lúc này trở đi ta xem ~n := n / gcd~ và ~k := 2 \times k / gcd~ tương ứng với số đỉnh và khoảng cách bước nhảy khi nói về mỗi phần độc lập, các đỉnh trong mỗi phần đánh số từ ~0~.

Một vấn đề của subtask này là trong mỗi phần, có thể có nhiều đỉnh xuất phát, vì thế ta cần tìm cách để giải quyết những đỉnh được thăm trùng lặp. Gọi ~d[i]~ là thời gian mà đỉnh ~i~ được thăm nếu xuất phát từ đỉnh ~0~, vậy thì với mỗi đỉnh ~i~ trong bàn tròn, ta sẽ đánh dấu các số từ ~d[i]~ đến ~(d[i] + k) \% n~, ta có thể sử dụng kỹ thuật 2 con trỏ để giải quyết tuyến tính bài toán này.

Vậy cách tìm ~d[i]~ như thế nào, đơn giản là ~d[i]~ cần thỏa ~(0 + d[i] \times k) \equiv i (mod n)~, nói cách khác là ~i + j \times n = d[i] \times k (j \in \mathbb{Z})~ hay ~d[i] \times k + j \times n = i (j \in \mathbb{Z})~. Phương trình trên chính là dạng ~ax+by=c~ có thể giải bằng cách tìm nghiệm của ~ax+by=gcd(a, b)~ rồi nhân nghiệm 1 khoảng ~c/gcd(a, b)~, ở phương trình trên thì ~(a, b, c, x, y) = (k, n, i, d[i], j)~ và dễ thấy ~gcd(k, n) = 1~ nên khoảng phải nhân thêm đơn giản chỉ là ~i~. Lưu ý khi tìm thấy nghiệm ~d[i]~ bằng thuật Extended Euclid thì phải đưa ~d[i]~ về với giới hạn ~0 \le d[i] < n~.

Độ phức tạp thuật toán: ~O(log(m))~.


Comments

Please read the guidelines before commenting.


There are no comments at the moment.