| # | Bài tập | Điểm | Thời gian: | Giới hạn bộ nhớ |
|---|---|---|---|---|
| 1 | APIO 2022 - Mars | 100 (p) | 3.0s | 256M |
| 2 | APIO 2022 - Game | 100 (p) | 3.0s | 256M |
| 3 | APIO 2022 - Permutation | 100 (p) | 1.0s | 256M |
Như đã biết, các Pharaoh là những người đầu tiên khám phá vũ trụ. Họ đã phóng con tàu vũ trụ đầu tiên lên hành tinh Thutmus I (ngày nay được biết đến với tên gọi Sao Hỏa). Bề mặt hành tinh có thể được mô hình hóa bằng một lưới gồm \((2n+1)\times(2n+1)\) ô vuông, mỗi ô chứa đất hoặc nước. Trạng thái của ô ở hàng \(i\), cột \(j\) (\(0\le i,j\le 2n\)) được ký hiệu bởi \(s[i][j]\): \(s[i][j]=\) '1' nếu ô chứa đất và \(s[i][j]=\) '0' nếu ô chứa nước.
Hai ô đất được gọi là liên thông nếu tồn tại một đường đi chỉ gồm các ô đất nối chúng, trong đó hai ô liên tiếp luôn có chung một cạnh. Một hòn đảo trên hành tinh là một tập tối đại các ô đất sao cho hai ô bất kỳ trong tập đều liên thông với nhau.
Nhiệm vụ của con tàu là đếm số hòn đảo trên hành tinh. Tuy nhiên, nhiệm vụ này không dễ dàng vì con tàu sử dụng một máy tính cổ đại. Máy tính có bộ nhớ \(h\), là một mảng hai chiều kích thước \((2n+1)\times(2n+1)\). Mỗi phần tử của mảng chứa được một xâu nhị phân độ dài \(100\), trong đó mỗi ký tự là '0' (ASCII 48) hoặc '1' (ASCII 49). Ban đầu, ký tự đầu tiên của mỗi ô nhớ lưu trạng thái của ô tương ứng trên lưới:
với mọi \(0\le i,j\le 2n\). Tất cả các ký tự còn lại của \(h\) ban đầu đều là '0' (ASCII 48).
Để xử lý dữ liệu trong bộ nhớ, máy tính chỉ có thể truy cập một vùng \(3\times3\) và ghi đè giá trị tại ô trên cùng bên trái của vùng đó. Cụ thể, máy tính có thể truy cập các giá trị \(h[i..i+2][j..j+2]\) (\(0\le i,j\le 2(n-1)\)) rồi ghi đè giá trị tại \(h[i][j]\). Thao tác này được gọi là xử lý ô \((i,j)\).
Để khắc phục giới hạn của máy tính, các Pharaoh sử dụng cơ chế sau:
Hình dưới đây minh họa cách máy tính xử lý một bộ nhớ kích thước \(5\times5\) (\(n=2\)). Ô màu xanh lam là ô đang bị ghi đè; các ô được tô màu tạo thành vùng đang được xử lý.
Trong bước \(0\), máy tính xử lý các vùng dưới đây theo thứ tự từ trái sang phải:
Trong bước \(1\), máy tính chỉ xử lý một vùng:
Hãy cài đặt một phương pháp cho phép máy tính đếm số hòn đảo trên hành tinh Thutmus I theo đúng cơ chế hoạt động trên.
Bạn cần cài đặt hàm sau. Chữ ký C++ trong tệp tiêu đề chính thức là:
std::string process(std::vector<std::vector<std::string>> a,
int i, int j, int k, int n);
a: mảng \(3\times3\) biểu diễn vùng đang được xử lý; cụ thể, \(a=h[i..i+2][j..j+2]\). Mỗi phần tử của a là một xâu có độ dài đúng bằng \(100\), và mỗi ký tự là '0' (ASCII 48) hoặc '1' (ASCII 49).i, j: lần lượt là chỉ số hàng và cột của ô máy tính đang xử lý.k: chỉ số của bước hiện tại.n: tổng số bước; bề mặt hành tinh có kích thước \((2n+1)\times(2n+1)\) ô.Mỗi test chứa \(T\) kịch bản độc lập, tương ứng với các bề mặt hành tinh khác nhau. Hoạt động của lời giải cho mỗi kịch bản phải độc lập với thứ tự của các kịch bản, vì các lời gọi process thuộc cùng một kịch bản có thể không diễn ra liên tiếp nhau. Tuy nhiên, đối với từng kịch bản, các lời gọi process được bảo đảm xuất hiện theo đúng trình tự đã mô tả ở trên.
Ngoài ra, trong mỗi test, nhiều phiên bản chương trình của bạn có thể được khởi chạy đồng thời. Giới hạn thời gian và bộ nhớ được tính gộp cho tất cả các phiên bản này. Mọi hành vi cố ý truyền dữ liệu ngoài giao thức giữa các phiên bản chương trình đều bị coi là gian lận và có thể dẫn đến việc bị loại khỏi kỳ thi.
Đặc biệt, mọi thông tin lưu trong biến tĩnh hoặc biến toàn cục trong một lần gọi process không được bảo đảm còn tồn tại ở các lần gọi tiếp theo.
'0' (ASCII 48) hoặc '1' (ASCII 49), với mọi \(0\le i,j\le2n\).'0' (ASCII 48) hoặc '1' (ASCII 49), với mọi \(0\le i,j\le2n\).Trong mỗi lần gọi process:
Ví dụ 1
Xét \(n=1\) và ma trận \(s\) sau:
'1' '0' '0'
'1' '1' '0'
'0' '0' '1'
Bề mặt hành tinh gồm \(3\times3\) ô và có \(2\) hòn đảo. Chỉ có một bước gọi hàm process.
Trong bước \(0\), trình chấm gọi process đúng một lần:
process([["100","000","000"],["100","100","000"],["000","000","100"]],0,0,0,1)
Trong lời gọi trên, chỉ ba bit đầu tiên của mỗi ô nhớ \(h\) được hiển thị.
Hàm phải trả về "0100...", trong đó mọi bit bị lược bỏ đều bằng \(0\). Khi đọc theo thứ tự bit thông thường, ....0010 trong hệ nhị phân bằng \(2\) trong hệ thập phân. Có \(96\) ký tự 0 bị lược bỏ và thay bằng ....
Ví dụ 2
Xét \(n=2\) và ma trận \(s\) sau:
'1' '1' '0' '1' '1'
'1' '1' '0' '0' '0'
'1' '0' '1' '1' '1'
'0' '1' '0' '0' '0'
'0' '1' '1' '1' '1'
Bề mặt hành tinh gồm \(5\times5\) ô và có \(4\) hòn đảo. Có \(2\) bước gọi hàm process.
Trong bước \(0\), trình chấm gọi process chín lần:
process([["100","100","000"],["100","100","000"],["100","000","100"]],0,0,0,2)
process([["100","000","100"],["100","000","000"],["000","100","100"]],0,1,0,2)
process([["000","100","100"],["000","000","000"],["100","100","100"]],0,2,0,2)
process([["100","100","000"],["100","000","100"],["000","100","000"]],1,0,0,2)
process([["100","000","000"],["000","100","100"],["100","000","000"]],1,1,0,2)
process([["000","000","000"],["100","100","100"],["000","000","000"]],1,2,0,2)
process([["100","000","100"],["000","100","000"],["000","100","100"]],2,0,0,2)
process([["000","100","100"],["100","000","000"],["100","100","100"]],2,1,0,2)
process([["100","100","100"],["000","000","000"],["100","100","100"]],2,2,0,2)
Giả sử các lời gọi trên lần lượt trả về "011", "000", "000", "111", "111", "011", "110", "010", "111", trong đó các bit bị lược bỏ đều bằng \(0\). Sau khi bước \(0\) kết thúc, \(h\) chứa:
"011", "000", "000", "100", "100"
"111", "111", "011", "000", "000"
"110", "010", "111", "100", "100"
"000", "100", "000", "000", "000"
"000", "100", "100", "100", "100"
Trong bước \(1\), trình chấm gọi process một lần:
process([["011","000","000"],["111","111","011"],["110","010","111"]],0,0,1,2)
Cuối cùng, hàm phải trả về "0010000....", trong đó mọi bit bị lược bỏ đều bằng \(0\). Khi đọc theo thứ tự bit thông thường, ....0000100 trong hệ nhị phân bằng \(4\) trong hệ thập phân. Có \(93\) ký tự 0 bị lược bỏ và thay bằng ....
Trình chấm mẫu đọc dữ liệu theo định dạng sau; đây chỉ là giao diện của trình chấm mẫu, không phải giao diện chuẩn vào/ra của bài:
Trình chấm mẫu in trên dòng \(1+i\) giá trị trả về cuối cùng của process cho kịch bản thứ \(i\) dưới dạng thập phân.
Đề bài chính thức của Ban tổ chức APIO 2022, Ai Cập: gói nguồn chính thức của bài Mars.
Sau khi khám phá \(n\) hành tinh được đánh số từ \(0\) đến \(n-1\), các Pharaoh bắt đầu xây dựng một hệ thống giao thông giữa chúng bằng các đường dịch chuyển một chiều. Mỗi đường dịch chuyển có một hành tinh xuất phát và một hành tinh đích. Khi một du khách sử dụng đường dịch chuyển tại hành tinh xuất phát, họ được dịch chuyển đến hành tinh đích. Hành tinh xuất phát và hành tinh đích có thể trùng nhau. Đường dịch chuyển có hành tinh xuất phát \(u\) và hành tinh đích \(v\) được ký hiệu là \((u,v)\).
Để khuyến khích việc sử dụng rộng rãi hệ thống dịch chuyển, các Pharaoh tạo ra một trò chơi cho du khách trong khi di chuyển. Du khách có thể bắt đầu trò chơi từ bất kỳ hành tinh nào. Các hành tinh \(0,1,\ldots,k-1\) (\(k\le n\)) được gọi là hành tinh đặc biệt. Mỗi lần đi vào một hành tinh đặc biệt, du khách nhận được một con tem.
Ban đầu, với mỗi \(i\) (\(0\le i\le k-2\)), tồn tại một đường dịch chuyển \((i,i+1)\). Các đường dịch chuyển này, có tổng cộng \(k-1\) đường, được gọi là đường dịch chuyển ban đầu.
Các đường dịch chuyển mới được thêm lần lượt từng đường một. Khi các đường mới được thêm vào, du khách có thể bắt đầu nhận được vô hạn tem. Cụ thể, điều này xảy ra khi tồn tại một dãy các hành tinh \(w[0],w[1],\ldots,w[t]\) thỏa mãn:
Du khách được phép sử dụng các đường dịch chuyển ban đầu và mọi đường dịch chuyển đã được thêm cho đến thời điểm hiện tại.
Hãy giúp các Pharaoh xác định, sau mỗi lần thêm một đường dịch chuyển, liệu du khách có thể nhận được vô hạn tem hay không.
Bạn cần cài đặt hai hàm sau. Chữ ký C++ trong tệp tiêu đề chính thức là:
void init(int n, int k);
int add_teleporter(int u, int v);
Hàm init:
n: số hành tinh.k: số hành tinh đặc biệt.add_teleporter.Hàm add_teleporter:
u, v: hành tinh xuất phát và hành tinh đích của đường dịch chuyển vừa được thêm.Trong mỗi lần gọi add_teleporter:
Ví dụ 1
Trình chấm gọi:
init(6, 3);
Có \(6\) hành tinh và \(3\) hành tinh đặc biệt. Các hành tinh \(0\), \(1\), \(2\) là hành tinh đặc biệt; các đường dịch chuyển ban đầu là \((0,1)\) và \((1,2)\).
Sau đó, giả sử trình chấm thực hiện các lời gọi sau:
add_teleporter(3, 4): phải trả về \(0\).add_teleporter(5, 0): phải trả về \(0\).add_teleporter(4, 5): phải trả về \(0\).add_teleporter(5, 3): phải trả về \(0\).add_teleporter(1, 4): lúc này du khách có thể nhận được vô hạn tem. Chẳng hạn, du khách bắt đầu ở hành tinh \(0\) rồi lần lượt đi đến \(1,4,5,0,1,4,5,0,\ldots\). Vì vậy, hàm phải trả về \(1\) và chương trình sẽ bị dừng.Ví dụ 2
Trình chấm gọi:
init(4, 2);
Có \(4\) hành tinh và \(2\) hành tinh đặc biệt. Các hành tinh \(0\), \(1\) là hành tinh đặc biệt; đường dịch chuyển ban đầu là \((0,1)\).
Sau đó, trình chấm gọi add_teleporter(1, 1). Khi thêm đường dịch chuyển \((1,1)\), du khách có thể bắt đầu ở hành tinh \(1\) và đi vào hành tinh \(1\) vô hạn lần bằng chính đường dịch chuyển này. Vì vậy, hàm phải trả về \(1\) và chương trình sẽ bị dừng.
Trình chấm mẫu đọc dữ liệu theo định dạng sau; đây chỉ là giao diện của trình chấm mẫu, không phải giao diện chuẩn vào/ra của bài:
Đầu tiên, trình chấm mẫu gọi init(n, k). Sau đó, với \(i=0,1,\ldots,m-1\) theo đúng thứ tự, trình chấm gọi add_teleporter(u[i], v[i]).
Trình chấm mẫu in chỉ số của lời gọi add_teleporter đầu tiên trả về \(1\) (một số từ \(0\) đến \(m-1\)), hoặc in \(m\) nếu tất cả các lời gọi đều trả về \(0\). Nếu một lời gọi trả về số nguyên khác \(0\) và \(1\), trình chấm mẫu in \(-1\) rồi dừng chương trình ngay lập tức.
Các tệp ví dụ chính thức dành cho trình chấm mẫu là:
Tệp mẫu 1
6 5 3
3 4
5 0
4 5
5 3
1 4
4
Tệp này tương ứng với Ví dụ 1.
Tệp mẫu 2
4 1 2
1 1
0
Tệp này tương ứng với Ví dụ 2.
Tệp mẫu 3
4 3 2
1 3
2 0
3 2
2
Đề bài chính thức của Ban tổ chức APIO 2022, Ai Cập: gói nguồn chính thức của bài Game.
Các Pharaoh sử dụng chuyển động tương đối và lực hấp dẫn của các hành tinh để tăng tốc phi thuyền. Giả sử một phi thuyền lần lượt đi qua \(n\) hành tinh có tốc độ quỹ đạo \(p[0],p[1],\ldots,p[n-1]\). Với mỗi hành tinh, các nhà khoa học của Pharaoh có thể chọn dùng hành tinh đó để tăng tốc phi thuyền hoặc không. Để tiết kiệm năng lượng, sau khi tăng tốc bằng một hành tinh có tốc độ quỹ đạo \(p[i]\), phi thuyền không thể tiếp tục được tăng tốc bằng bất kỳ hành tinh nào có tốc độ quỹ đạo \(p[j]<p[i]\).
Nói cách khác, các hành tinh được chọn tạo thành một dãy con tăng dần của \(p[0],p[1],\ldots,p[n-1]\). Một dãy con của \(p\) là một dãy thu được bằng cách xóa đi không, một hoặc nhiều phần tử của \(p\) mà không thay đổi thứ tự các phần tử còn lại. Chẳng hạn, \([0]\), \([]\), \([0,2]\) và \([0,1,2]\) là các dãy con của \([0,1,2]\), còn \([2,1]\) thì không.
Các nhà khoa học xác định rằng có tổng cộng \(k\) cách khác nhau để chọn một nhóm hành tinh nhằm tăng tốc phi thuyền, nhưng họ đã làm mất toàn bộ dữ liệu về tốc độ quỹ đạo, kể cả giá trị \(n\). Tuy nhiên, họ nhớ rằng \((p[0],p[1],\ldots,p[n-1])\) là một hoán vị của \(0,1,\ldots,n-1\). Một hoán vị là một dãy chứa mỗi số nguyên từ \(0\) đến \(n-1\) đúng một lần. Hãy tìm một hoán vị \(p[0],p[1],\ldots,p[n-1]\) có thể xảy ra và có độ dài đủ nhỏ.
Bạn cần giải bài toán cho \(q\) phi thuyền khác nhau. Với phi thuyền thứ \(i\), bạn nhận được số nguyên \(k_i\), là số cách khác nhau để chọn một nhóm hành tinh tăng tốc phi thuyền. Hãy tìm một dãy tốc độ quỹ đạo có độ dài \(n_i\) đủ nhỏ sao cho có đúng \(k_i\) cách chọn một dãy con các hành tinh với tốc độ quỹ đạo tăng dần.
Lưu ý rằng dãy con rỗng cũng được tính là một dãy con tăng dần.
Bạn cần cài đặt hàm sau. Chữ ký C++ trong tệp tiêu đề chính thức là:
std::vector<int> construct_permutation(long long k);
k: số dãy con tăng dần mong muốn.(\(90\) điểm) Không có ràng buộc bổ sung. Gọi \(m\) là độ dài lớn nhất trong tất cả các hoán vị bạn trả về. Điểm của phân nhóm này được tính như sau:
| Điều kiện | Điểm |
|---|---|
| \(m\le90\) | \(90\) |
| \(90<m\le120\) | \(90-\dfrac{m-90}{3}\) |
| \(120<m\le5000\) | \(80-\dfrac{m-120}{65}\) |
| \(m>5000\) | \(0\) |
Ví dụ 1
Xét lời gọi:
construct_permutation(3);
Hàm phải trả về một hoán vị có đúng \(3\) dãy con tăng dần. Một kết quả hợp lệ là \([1,0]\), có ba dãy con tăng dần: \([]\) (dãy rỗng), \([0]\) và \([1]\).
Ví dụ 2
Xét lời gọi:
construct_permutation(8);
Hàm phải trả về một hoán vị có đúng \(8\) dãy con tăng dần. Một kết quả hợp lệ là \([0,1,2]\).
Trình chấm mẫu đọc dữ liệu theo định dạng sau; đây chỉ là giao diện của trình chấm mẫu, không phải giao diện chuẩn vào/ra của bài:
Với mỗi \(k_i\), trình chấm mẫu in trên một dòng giá trị mà construct_permutation trả về, hoặc một thông báo lỗi nếu xảy ra lỗi.
Tệp ví dụ chính thức dành cho trình chấm mẫu là:
Tệp mẫu 1
2
3
8
2
1 0
3
0 1 2
Đề bài chính thức của Ban tổ chức APIO 2022, Ai Cập: gói nguồn chính thức của bài Permutation.