| # | Bài tập | Điểm | Thời gian: | Giới hạn bộ nhớ |
|---|---|---|---|---|
| 1 | CEOI 2025 - Equalmex | 100 (p) | 2.0s | 1G |
| 2 | CEOI 2025 - Splits | 100 (p) | 2.0s | 1G |
| 3 | CEOI 2025 - Theseus | 100 (p) | 2.0s | 400M |
Với một mảng số nguyên \(a[0],a[1],\ldots,a[m-1]\), gọi vẻ đẹp của mảng là số lượng số nguyên dương \(k\) sao cho có thể chia mảng thành \(k\) mảng con rời nhau, mỗi mảng con là một dãy phần tử liên tiếp, mỗi phần tử của mảng ban đầu thuộc đúng một mảng con, và tất cả các mảng con đều có cùng số nguyên dương nhỏ nhất không xuất hiện.
Số nguyên dương nhỏ nhất không xuất hiện của một mảng là số nguyên nhỏ nhất lớn hơn \(0\) không xuất hiện trong mảng đó.
Cho mảng số nguyên \(v[0],v[1],\ldots,v[n-1]\) và \(q\) truy vấn \((l_i,r_i)\), trong đó \(0\le l_i\le r_i<n\). Với mỗi truy vấn, hãy tìm vẻ đẹp của mảng
Bạn cần cài đặt hàm sau:
std::vector<int> solve(
int n,
std::vector<int>& v,
int q,
std::vector<std::pair<int, int>>& queries
);
n: kích thước của mảng số nguyên.v: mảng ban đầu có độ dài \(n\).q: số truy vấn.queries: mảng độ dài \(q\) mô tả các truy vấn; phần tử thứ \(i\) là cặp \((l_i,r_i)\).queries đều bắt đầu từ \(0\). Dữ liệu kiểm thử thô chính thức lưu hai đầu mút bắt đầu từ \(1\); trình chấm chuyển chúng về chỉ số bắt đầu từ \(0\) trước khi gọi solve.Ví dụ 1
solve(
10,
{1, 1, 2, 2, 3, 3, 1, 2, 3, 4},
2,
{{0, 5}, {0, 8}}
)
{1, 2}
Ở truy vấn đầu tiên, chỉ có thể chia đoạn thành một mảng con, từ vị trí \(0\) đến vị trí \(5\).
Ở truy vấn thứ hai, \(k\) có thể bằng \(1\) hoặc \(2\). Với \(k=1\), lấy một mảng con từ vị trí \(0\) đến vị trí \(8\). Với \(k=2\), có thể chia thành mảng con từ vị trí \(0\) đến vị trí \(5\) và mảng con từ vị trí \(6\) đến vị trí \(8\).
Vì vậy đáp án của hai truy vấn lần lượt là \(1\) và \(2\).
Trình chấm mẫu đọc dữ liệu theo định dạng sau:
n q.v[0] v[1] ... v[n-1].l_i r_i, sử dụng chỉ số bắt đầu từ \(0\) như giao diện solve.Trình chấm mẫu in \(q\) dòng là các phần tử của mảng do solve trả về.
Cho một hoán vị
của các số \(1,2,\ldots,n\). Một phép tách của \(p\) là một hoán vị \(q\) có thể thu được bằng quy trình sau:
Ký hiệu \(S(p)\) là tập hợp tất cả các phép tách của hoán vị \(p\).
Cho số nguyên \(n\) và một tập \(T\) gồm \(m\) hoán vị độ dài \(n\). Hãy đếm số hoán vị \(p\) độ dài \(n\) thỏa mãn
Vì kết quả có thể rất lớn, hãy trả về kết quả theo modulo \(998\,244\,353\).
Bạn cần cài đặt hàm sau:
int solve(
int n,
int m,
std::vector<std::vector<int>>& splits
);
n: độ dài của mỗi hoán vị.m: số phép tách được cho.splits: mảng gồm \(m\) hoán vị đôi một phân biệt, chính là các phần tử của tập \(T\).Ví dụ 1
solve(3, 2, {{1, 2, 3}, {2, 1, 3}})
4
Trong ví dụ này, \(p\) có độ dài \(3\) và hai phép tách được cho là \(123\) và \(213\). Chỉ có bốn hoán vị có thể sinh ra cả hai phép tách ấy:
123
132
213
231
Trình chấm mẫu đọc dữ liệu theo định dạng sau:
n m.splits[i][0] splits[i][1] ... splits[i][n-1].Trình chấm mẫu in kết quả của lời gọi solve với các tham số tương ứng.
Nếu từng bộ phận của con tàu Theseus lần lượt được thay thế theo thời gian, thì vào thời điểm nào, nếu có, nó không còn là cùng một con tàu nữa?
Khi không suy ngẫm về những vấn đề trừu tượng, Theseus dành thời gian rảnh để tiêu diệt Minotaur. Tuy nhiên, lần này anh phải đi qua một mê cung tối tăm và ngoằn ngoèo trước. Vì đây không phải việc dễ dàng, Theseus nhờ Ariadne dẫn đường.
Mê cung được biểu diễn bởi một đồ thị vô hướng liên thông gồm \(n\) đỉnh, đánh số từ \(1\) đến \(n\), và \(m\) cạnh. Có một đỉnh đặc biệt \(t\) là nơi Minotaur đang ở.
Theseus hoàn toàn không nhìn thấy đồ thị, còn Ariadne nhìn thấy toàn bộ. Họ sẽ thống nhất một chiến lược để Theseus có thể đến đỉnh chứa Minotaur một cách an toàn: Ariadne gắn nhãn \(0\) hoặc \(1\) lên mỗi cạnh. Sau đó Theseus đi vào mê cung tại một đỉnh \(s\) mà Ariadne không biết trước.
Do mê cung rất tối, tại mỗi thời điểm Theseus chỉ nhìn thấy chỉ số của đỉnh hiện tại, chỉ số của các đỉnh kề và nhãn của các cạnh kề. Hơn nữa, vì mê cung rất ngoằn ngoèo, anh không thể nhớ bất kỳ thông tin nào về những đỉnh đã đi qua trước đó.
Để đến chỗ Minotaur an toàn, Theseus phải thực hiện không quá
bước đi, trong đó \(\operatorname{dist}(s,t)\) là số cạnh ít nhất trên một đường đi từ \(s\) đến \(t\), và \(C\) là một hằng số.
Bạn cần cài đặt hai hàm sau.
std::vector<int> paint(
int n,
std::vector<std::pair<int, int>> edges,
int t
);
n: số đỉnh của đồ thị.edges: danh sách độ dài \(m\) mô tả các cạnh của đồ thị.t: đỉnh đích.edges và phải bằng \(0\) hoặc \(1\).int travel(
int n,
int u,
std::vector<std::pair<int, int>> neighbours
);
n: số đỉnh của đồ thị.u: đỉnh hiện tại.neighbours: danh sách các cặp \((v,e)\), cho biết có một cạnh nối \(u\) với \(v\) và cạnh ấy mang nhãn \(e\).Chú ý: Các lời gọi paint và travel được thực hiện trong các tiến trình độc lập. Chương trình không được dùng biến toàn cục hoặc biến static để truyền thông tin giữa các thực thể khác nhau của paint hoặc travel. Mọi hành vi cố lách yêu cầu này đều dẫn đến hành vi không được xác định.
label.Đồ thị bậc thang gồm hai đường đi song song có cùng độ dài; mỗi cặp đỉnh tương ứng trên hai đường đi được nối bằng một cạnh để tạo thành các bậc thang. Ở một đầu của bậc thang có đỉnh đặc biệt \(t\), là đỉnh đích, được nối với cả hai đầu mút ở phía đó và đóng vai trò như một đỉnh cha chung. Với mọi đồ thị như vậy, \(n\) luôn là số lẻ.
![Minh họa đồ thị bậc thanghttps://cdn.lqdoj.edu.vn/media/pagedown-uploads/pd_7_963affdb.png
Xét đồ thị có \(7\) đỉnh và \(7\) cạnh dưới đây. Đỉnh xuất phát là \(3\), được tô màu xanh lá; đỉnh đích là \(7\), được tô màu đỏ.
![Đồ thị trong ví dụ Theseushttps://cdn.lqdoj.edu.vn/media/pagedown-uploads/pd_7_388d02c1.png
Đầu tiên, trình chấm gọi paint. Giả sử hàm trả về dãy nhãn sau:
| Lời gọi | Giá trị trả về |
|---|---|
paint(7, {{1, 6}, {7, 6}, {2, 5}, {3, 2}, {3, 6}, {6, 5}, {6, 4}}, 7) |
{0, 1, 1, 1, 0, 1, 0} |
Khi ấy, một chuỗi lời gọi travel hợp lệ đưa Theseus đến đích là:
| Lời gọi | Giá trị trả về |
|---|---|
travel(7, 3, {{2, 1}, {6, 0}}) |
2 |
travel(7, 2, {{5, 1}, {3, 1}}) |
5 |
travel(7, 5, {{6, 1}, {2, 1}}) |
6 |
travel(7, 6, {{3, 0}, {5, 1}, {1, 0}, {4, 0}, {7, 1}}) |
4 |
travel(7, 4, {{6, 0}}) |
6 |
travel(7, 6, {{3, 0}, {5, 1}, {1, 0}, {4, 0}, {7, 1}}) |
7 |
Khi giá trị trả về là \(7\), tức đỉnh đích, chương trình dừng lại.
Trình chấm mẫu đọc dữ liệu theo định dạng sau:
n m.s t.a b, biểu diễn một cạnh nối hai đỉnh \(a\) và \(b\).Đầu tiên, trình chấm gọi paint với các tham số tương ứng và gắn nhãn cho các cạnh theo danh sách trả về. Sau đó, trình chấm gọi travel với các tham số \(n\), \(s\) và danh sách các đỉnh kề của \(s\). Sau lời gọi đầu tiên, trình chấm tiếp tục gọi travel, lấy đỉnh hiện tại là đỉnh do lời gọi trước trả về, cho đến khi đạt đỉnh đích \(t\).
Với mỗi bước, trình chấm mẫu in đỉnh hiện tại và đỉnh do travel trả về. Cuối cùng, trình chấm in tổng số bước đi.