| # | Bài tập | Điểm | Thời gian: | Giới hạn bộ nhớ |
|---|---|---|---|---|
| 1 | IOI 2026 Ngày 2 Bài 1 - Classroom Game | 100 (p) | 0.5s | 1G |
| 2 | IOI 2026 Ngày 2 Bài 2 - Magic City | 100 (p) | 0.5s | 2G |
| 3 | IOI 2026 Ngày 2 Bài 3 - Partition | 100 (p) | 1.0s | 2G |
Một trường trung học danh tiếng ở Tashkent tổ chức lễ kỷ niệm ngày thành lập bằng cách tổ chức một trò chơi giữa học sinh và giáo viên. Có \(N\) học sinh, được đánh số từ \(0\) đến \(N - 1\), đang ngồi trong lớp học. Mỗi học sinh cầm một tờ giấy có chứa một mảng các số nguyên. Ban đầu, mỗi tờ giấy đều trống, do đó tờ giấy chứa một mảng rỗng.
Các học sinh đang tham gia trò chơi với \(M\) giáo viên, được đánh số từ \(0\) đến \(M - 1\), và với hiệu trưởng. Trò chơi diễn ra trong \(M\) bước, cũng được đánh số từ \(0\) đến \(M - 1\). Trong bước \(j\), giáo viên \(j\) bước vào lớp học và diễn ra các sự kiện sau đây:
Khi tất cả \(M\) bước đã hoàn tất và lần trao đổi cuối cùng theo \(P\) được thực hiện, hiệu trưởng bước vào. Chỉ nhìn vào các tờ giấy mà các học sinh đang cầm, hiệu trưởng phải xác định, đối với mỗi học sinh \(i\) (\(0 \le i < N\)), bước \(j\) mà học sinh \(i\) đã giơ tay, hoặc kết luận rằng học sinh \(i\) chưa bao giờ giơ tay.
Giáo viên không được phép trao đổi với các giáo viên khác hoặc với hiệu trưởng, ngoại trừ việc thông qua các dãy số nguyên được viết trên các tờ giấy. Mỗi giáo viên đều biết tại bước nào họ bước vào lớp học.
Nhiệm vụ của bạn là thiết kế và cài đặt một chiến lược cho các giáo viên và hiệu trưởng để xác định chính xác liệu mỗi học sinh có giơ tay hay không và vào thời điểm nào. Điểm số của bạn sẽ phụ thuộc vào độ dài tối đa của bất kỳ dãy số nào được viết trên một tờ giấy: độ dài tối đa này càng ngắn thì điểm số của bạn có thể càng cao hoặc bằng.
Bạn cần cài đặt hai hàm, một dành cho các giáo viên và một dành cho hiệu trưởng.
Hàm bạn cần cài đặt cho các giáo viên là:
std::vector<std::vector<int>> process_step(
int N, int M, int R,
std::vector<int> T,
std::vector<std::vector<int>> A)
N: số lượng học sinh.M: số lượng bước, và cũng là số lượng giáo viên.R: số hiệu bước hiện tại (từ \(0\) đến \(M - 1\)).T: một mảng (có thể rỗng) chứa các chỉ số của các học sinh giơ tay trong bước này, sắp xếp theo thứ tự tăng dần.A: một mảng kích thước \(N\) mô tả các tờ giấy, trong đó \(A[i]\) (\(0 \le i < N\)) là mảng các số nguyên trên tờ giấy mà học sinh \(i\) đang cầm vào đầu bước này.Hàm này cần trả về một mảng \(B\) kích thước \(N\), chứa các tờ giấy sau khi giáo viên chỉnh sửa, theo cùng định dạng như \(A\).
Hàm bạn cần cài đặt cho hiệu trưởng là:
std::vector<int> determine_steps(
int N, int M, std::vector<std::vector<int>> A)
N, M: giống như trên.A: một mảng kích thước \(N\), trong đó \(A[i]\) là mảng các số nguyên trên tờ giấy của học sinh \(i\) sau toàn bộ \(M\) bước.process_step.Hàm này phải trả về một mảng \(D\) kích thước \(N\). Với mỗi \(i\) sao cho \(0 \le i < N\), mảng phải thỏa mãn điều kiện sau:
Chương trình của bạn không được phép lưu trữ hoặc truyền bất kỳ thông tin nào từ một lời gọi hàm process_step sang lời gọi khác, trừ khi thông qua giá trị trả về của hàm process_step. Nếu chương trình của bạn cố gắng thực hiện điều này, điểm số của bạn trên CMS có thể không chính xác và có thể bị trừ sau khi cuộc thi kết thúc. Lưu ý rằng trình chấm có thể chạy nhiều tiến trình của chương trình của bạn cùng lúc. Điều này có nghĩa là các lời gọi đến process_step và determine_steps từ cùng một trò chơi có thể được chạy trong các tiến trình khác nhau, và các lời gọi đến process_step và determine_steps từ các trò chơi khác nhau có thể được chạy trong cùng một tiến trình. Mỗi trường hợp test bao gồm tối đa \(5\) trò chơi.
| Subtask | Điểm | Các ràng buộc thêm |
|---|---|---|
| 1 | 4 | \(M = 1\). |
| 2 | 6 | \(N = 2\). |
| 3 | 9 | \(P[i] = i\) với mọi \(0 \le i \le N - 1\). |
| 4 | 25 | Có tối đa một học sinh giơ tay tại mỗi bước. |
| 5 | 56 | Không có ràng buộc nào thêm. |
Đối với mỗi trường hợp test, điểm số của bạn sẽ là \(0\) (được hiển thị dưới dạng Output isn't correct trong CMS) nếu giá trị trả về của bất kỳ lời gọi nào đến hàm process_step là không hợp lệ hoặc nếu giá trị trả về của bất kỳ lời gọi nào đến hàm determine_steps là không chính xác.
Trái lại, gọi \(C\) là kích thước lớn nhất của bất kỳ mảng nào trong bất kỳ \(B\) nào được trả về bởi process_step. Khi đó, điểm số cho một trường hợp test trong một subtask có điểm số \(S\) được tính theo công thức \(S \cdot X\), trong đó \(X\) phụ thuộc vào \(C\) theo bảng sau:
| Điều kiện | \(X\) |
|---|---|
| \(C \le 2\) | \(1.00\) |
| \(C = 3\) | \(0.75\) |
| \(C = 4\) | \(0.55\) |
| \(5 \le C \le 13\) | \(0.50 - 0.03 \cdot (C - 5)\) |
| \(14 \le C \le 63\) | \(0.19 \cdot \frac{64 - C}{64 - 14} + 0.04\) |
Xét một kịch bản với \(N = 4\) học sinh, \(M = 2\) giáo viên và phép hoán vị \(P = [0, 3, 1, 2]\). Ban đầu, tất cả các tờ giấy đều trống.
Trình chấm trước tiên gọi:
process_step(4, 2, 0, [1], [[], [], [], []])
Học sinh \(1\) đã giơ tay, do đó tờ giấy của em này không thể được chỉnh sửa. Giáo viên \(0\) có thể quyết định ghi \([10]\) vào tờ giấy của học sinh \(0\), ghi \([1, 63, 4]\) vào tờ giấy của học sinh \(3\), và để trống tờ giấy của học sinh \(2\). Để thực hiện điều này, hàm phải trả về \(B = [[10], [], [], [1, 63, 4]]\).
Sau khi giáo viên \(0\) ra khỏi phòng, các học sinh trao đổi tờ giấy của mình theo phép \(P\). Sau khi trao đổi, các tờ giấy sẽ là \(A = [[10], [], [1, 63, 4], []]\).
Trình chấm bây giờ gọi:
process_step(4, 2, 1, [0, 3], [[10], [], [1, 63, 4], []])
Các học sinh \(0\) và \(3\) đã giơ tay, do đó tờ giấy của các em này không thể được sửa đổi. Giáo viên \(1\) có thể quyết định ghi \([0, 40]\) vào tờ giấy của học sinh \(1\) và ghi \([1, 50]\) vào tờ giấy của học sinh \(2\). Để thực hiện điều này, hàm phải trả về kết quả \(B = [[10], [0, 40], [1, 50], []]\).
Sau khi giáo viên \(1\) ra khỏi phòng, các tờ giấy lại được trao đổi theo quy tắc \(P\). Sau khi trao đổi, các tờ giấy sẽ là \(A = [[10], [1, 50], [], [0, 40]]\).
Cuối cùng, trình chấm gọi:
determine_steps(4, 2, [[10], [1, 50], [], [0, 40]])
Hàm này phải trả về mảng \(D = [1, 0, -1, 1]\) vì các học sinh \(0\) và \(3\) đã giơ tay ở bước \(1\), học sinh \(1\) đã giơ tay ở bước \(0\), và học sinh \(2\) chưa bao giờ giơ tay. Trong ví dụ này, \(C = 3\).
Định dạng dữ liệu vào:
N M
Q[0] Q[1] ... Q[N-1]
P[0] P[1] ... P[N-1]
Trong đó, \(Q\) là một mảng kích thước \(N\), với \(Q[i] = j\) nếu học sinh \(i\) giơ tay trong bước \(j\), hoặc \(Q[i] = -1\) nếu học sinh \(i\) không bao giờ giơ tay trong suốt trò chơi.
Định dạng kết quả ra:
Sau mỗi lời gọi hàm process_step, trình chấm mẫu sẽ in ra nội dung của các tờ giấy. Gọi \(K\) là kích thước của \(B\) và \(L[i]\) là kích thước của \(B[i]\) (với mỗi \(0 \le i < K\)). Trình chấm mẫu sẽ in ra \(B\) theo định dạng sau (kèm theo một dòng trống):
K
L[0] B[0][0] B[0][1] ... B[0][L[0]-1]
L[1] B[1][0] B[1][1] ... B[1][L[1]-1]
:
L[K-1] B[K-1][0] B[K-1][1] ... B[K-1][L[K-1]-1]
Trình chấm mẫu tiếp theo sẽ hoán vị các tờ giấy theo phép hoán vị \(P\). Nếu \(K \ne N\), trình chấm mẫu sẽ hiển thị thông báo lỗi và kết thúc ngay lập tức.
Sau khi gọi hàm determine_steps, trình chấm mẫu sẽ hiển thị kết quả:
C H
D[0] D[1] ... D[H-1]
Trong đó, \(H\) là kích thước của mảng \(D\) được trả về bởi determine_steps.
Nguồn: Đề bài chính thức IOI 2026, bản tiếng Việt (VNM), ngày 2 — Classroom Game (classroom).
Thị trưởng thủ đô Tashkent muốn thiết kế lại công viên giải trí nổi tiếng Magic City. Bạn được cho một số nguyên dương \(K\) và nhiệm vụ của bạn là thiết kế một công viên như sau:
Nghiên cứu thị trường cho thấy:
Để làm hài lòng tất cả du khách tiềm năng, thị trưởng đã đặt ra hai điều kiện đối với thiết kế của bạn.
Ta gọi một bộ ba loại có thứ tự \((t_1, t_2, t_3)\) với \(0 \le t_1, t_2, t_3 < 2K\) là thú vị nếu \(t_1 \ne t_2\) và \(t_2 \ne t_3\). Lưu ý rằng \(t_1\) có thể bằng \(t_3\). Do đó, có \(2K \cdot (2K - 1)^2\) bộ ba thú vị.
Điều kiện 1: Với mỗi bộ ba thú vị \((t_1, t_2, t_3)\), phải tồn tại ba điểm tham quan \(a_1, a_2, a_3\) (với \(0 \le a_1, a_2, a_3 < N\)) sao cho:
Việc có hay không có lối đi bộ giữa \(a_1\) và \(a_3\) là không quan trọng. Cũng cần lưu ý rằng khi \(t_1 = t_3\), điểm tham quan \(a_1\) và \(a_3\) có thể giống nhau.
Điều kiện 2: Mỗi điểm tham quan chỉ có thể là điểm kết thúc của tối đa \(K\) lối đi bộ.
Bài toán này bao gồm \(50\) subtask chỉ yêu cầu kết quả ra với cách chấm điểm thành phần. Mỗi subtask tương ứng với một giá trị cụ thể của \(K\), và bạn phải thiết kế một công viên đáp ứng tất cả các điều kiện trên cho giá trị \(K\) đó. Điểm số của bạn phụ thuộc vào số lượng điểm tham quan trong lời giải của bạn: ít điểm tham quan hơn sẽ cho điểm số cao hơn hoặc bằng.
Có hai cách để nộp lời giải, và bạn có thể sử dụng một trong hai cách cho mỗi subtask:
Để gửi lời giải của bạn thông qua gọi hàm, bạn cần cài đặt hàm sau:
std::pair<std::vector<int>,std::vector<std::pair<int, int>>> construct(int K)
Hàm này cần trả về một cặp \((T, E)\) mô tả một công viên giải trí. Giả sử \(M\) là số lượng lối đi bộ trong công viên của bạn.
Để gửi lời giải của bạn thông qua file kết quả ra, hãy tạo và gửi một file văn bản theo định dạng sau:
N M
T[0] T[1] ... T[N-1]
U[0] V[0]
U[1] V[1]
...
U[M-1] V[M-1]
Chú ý rằng lời giải của bạn phải đáp ứng các điều kiện sau để được coi là hợp lệ:
Có \(50\) subtask tương ứng với \(K\) từ \(1\) đến \(50\). Trong subtask thứ \(i\) (\(1 \le i \le 50\)), giá trị của \(K\) là \(i\).
Mỗi subtask có một điểm số \(S\) và một số lượng điểm tham quan mong muốn \(P\) theo bảng bên dưới.
| Subtask | \(S\) | \(P\) |
|---|---|---|
| 1 | 1 | 2 |
| 2 | 8 | 12 |
| 3 | 9 | 24 |
| 4 | 9 | 40 |
| 5 | 9 | 50 |
| 6–10 | 4 | \(12 \cdot K\) |
| 11–12 | 3 | \(12 \cdot K\) |
| 13–50 | 1 | \(12 \cdot K\) |
Đối với mỗi subtask, nếu lời giải của bạn không mô tả một công viên giải trí hợp lệ, thì điểm số của lời giải sẽ là \(0\) (được phản hồi là Output isn't correct trong CMS).
Ngược lại, điểm số của bạn được tính dựa trên \(N\) và các tham số \(S\) và \(P\) như sau:
| Điều kiện | Điểm |
|---|---|
| \(N \le P\) | \(S\) |
| \(P < N \le 2P\) | \(\left(0.4 + 0.3 \cdot \frac{2P - N}{P}\right) \cdot S\) |
| \(2P < N \le 2000\) | \(\left(0.1 + 0.3 \cdot \frac{2P}{N}\right) \cdot S\) |
Xét lời gọi hàm sau:
construct(1)
Trong ví dụ này, \(K = 1\), vậy có \(2K = 2\) loại điểm tham quan. Hình dưới đây mô tả một giải pháp hợp lệ với \(N = 4\) điểm tham quan và \(M = 2\) lối đi bộ. Các điểm tham quan \(0, 1, 2\) thuộc loại \(0\), và điểm tham quan \(3\) thuộc loại \(1\).
Có hai bộ ba thú vị:
Điều này có nghĩa là Điều kiện 1 được thỏa mãn.
Hàm có thể trả về cặp \(([0, 0, 0, 1], [(0, 1), (2, 3)])\). Chú ý rằng lời giải được cung cấp cho ví dụ này có thể không tối ưu với \(K = 1\).
Định dạng dữ liệu vào:
K
Định dạng kết quả ra:
N M
T[0] T[1] ... T[N-1]
U[0] V[0]
U[1] V[1]
...
U[M-1] V[M-1]
Chú ý rằng kết quả của trình chấm mẫu phù hợp với định dạng yêu cầu của file đầu ra.
Nguồn: Đề thi chính thức IOI 2026, ngày thi thứ hai, bản tiếng Việt (VNM).
Temur và trợ lý của anh, Ulug'bek, đang chuẩn bị một trò ảo thuật cho chương trình Uzbekistan Got Talent. Trò ảo thuật này xoay quanh việc Temur giải quyết một bài toán phân hoạch sau đây: phân chia một bộ các số nguyên dương đã cho thành \(K\) nhóm không rỗng sao cho tổng các phần tử trong mỗi nhóm đều bằng nhau. Nói cách khác, mỗi số nguyên trong bộ phải được gán vào đúng một trong \(K\) nhóm, và tổng các phần tử trong mỗi nhóm phải bằng nhau. Ví dụ, nếu bộ đã cho là \([2, 1, 6, 4, 5]\) và \(K = 3\), một cách phân chia hợp lệ sẽ là \([2, 4]\), \([1, 5]\) và \([6]\). Trong trường hợp này, tổng các phần tử trong mỗi nhóm chính xác là \(6\).
Trò ảo thuật được thực hiện như sau:
Nhiệm vụ của bạn là thiết kế và cài đặt một chiến lược cho Temur và Ulug'bek. Có thể chứng minh rằng, với các điều kiện ràng buộc đã cho, luôn tồn tại một chiến lược cho phép họ giải quyết thành công bài toán phân hoạch, bất kể mảng \(A\) nào do ban giám khảo cung cấp.
Bạn cần thực hiện hai hàm.
Hàm mà bạn cần cài đặt cho Ulug'bek là:
std::vector<int> add_numbers(std::vector<int> A, int K, int M)
Hàm này cần trả về một mảng \(C\) chứa các số nguyên mà Ulug'bek muốn thêm vào mảng ban đầu. Gọi \(S\) là kích thước của mảng \(C\).
Hàm mà bạn cần cài đặt cho Temur là:
std::vector<int> find_partition(std::vector<int> B, int K)
Hàm này cần trả về một mảng \(P\) biểu thị sự phân hoạch của \(B\) thành \(K\) nhóm không giao nhau.
Trong quá trình chấm thực tế, một chương trình gọi các hàm nêu trên sẽ được chạy đúng hai lần.
add_numbers được gọi một lần duy nhất. Mảng trả về được hệ thống chấm xử lý để tính ra mảng \(B\).find_partition được gọi một lần duy nhất.| Subtask | Điểm | Các ràng buộc thêm |
|---|---|---|
| 1 | 5 | \(N = 3\) |
| 2 | 4 | \(M = 1\) |
| 3 | 7 | \(M \le 2\) |
| 4 | 10 | \(N \le 10\) |
| 5 | 7 | \(K = 2\) |
| 6 | 12 | \(K \le 3\) |
| 7 | 17 | \(K \le 10\) |
| 8 | 20 | \(K \le 100\) |
| 9 | 18 | Không có ràng buộc nào thêm. |
Xét lời gọi hàm sau:
add_numbers([8, 2, 9, 6, 1, 5, 5], 3, 9)
Trong ví dụ này \(A = [8, 2, 9, 6, 1, 5, 5]\). Ta muốn phân hoạch các số thành \(K = 3\) nhóm. Ulug'bek có thể thêm các số từ \(1\) đến \(M = 9\).
Hàm có thể trả về \([5, 4]\), có nghĩa là Ulug'bek quyết định thêm \(S = 2\) số nguyên mới: \(5\) và \(4\). Điều này hợp lệ vì cả hai phần tử đều nằm giữa \(1\) và \(M = 9\).
Mảng mở rộng sau đó được sắp xếp và truyền cho Temur qua lời gọi sau:
find_partition([1, 2, 4, 5, 5, 5, 6, 8, 9], 3)
Ta có thể chia các số nguyên từ mảng này thành ba nhóm sau: \([1, 5, 9]\), \([2, 5, 8]\) và \([4, 5, 6]\). Lưu ý rằng tổng của mỗi nhóm này bằng \(15\). Để chỉ ra phân hoạch này, hàm cần trả về mảng \([0, 1, 2, 0, 1, 2, 2, 1, 0]\).
Định dạng dữ liệu vào:
N K M
A[0] A[1] ... A[N-1]
Định dạng kết quả ra:
Sau khi lời gọi hàm add_numbers hoàn tất, trình chấm mẫu sẽ:
S
C[0] C[1] ... C[S-1]
B[0] B[1] ... B[N+S-1]
Sau khi lời gọi find_partition hoàn tất, trình chấm sẽ đưa ra:
L
P[0] P[1] ... P[L-1]
Trong đó, \(L\) là kích thước của mảng \(P\) được trả về bởi find_partition.
Nguồn: Đề thi chính thức IOI 2026, ngày thi thứ hai, bản tiếng Việt (VNM).