Google Code Jam 2022 - Round 1B

Bộ đề bài

# Bài tập Điểm Thời gian: Giới hạn bộ nhớ
1 Google Code Jam 2022 - ASeDatAb 100 2.5s 1G
2 Google Code Jam 2022 - Controlled Inflation 35 1.0s 1G
3 Google Code Jam 2022 - Pancake Deque 25 1.5s 1G

1. Google Code Jam 2022 - ASeDatAb

Điểm: 100 Thời gian: 2.5s Bộ nhớ: 1G Input: bàn phím Output: màn hình

Một liên danh nghiên cứu đã tìm kiếm cơ sở dữ liệu tốt nhất có thể trong ba năm, nhưng họ vẫn gặp vấn đề. Cơ sở dữ liệu lưu giá trị dưới dạng các bản ghi chứa chuỗi nhị phân \(8\) bit. Không may, phần cài đặt hàm gán giá trị cho bản ghi bị lỗi.

Mỗi bản ghi của cơ sở dữ liệu là một chuỗi nhị phân \(8\) bit. Các bit được đánh chỉ số từ \(0\) đến \(7\) theo thứ tự từ trái sang phải. Khi nhận lệnh gán một bản ghi cụ thể thành giá trị mới \(V\), thay vì gán trực tiếp thành \(V\), cơ sở dữ liệu thực hiện các bước sau:

  1. Chọn một số nguyên \(r\) trong đoạn từ \(0\) đến \(7\), kể cả hai đầu, rồi tạo \(W\) bằng cách xoay \(V\) sang phải \(r\) vị trí. Nói cách khác, bit thứ \(((i+r)\bmod8)\) của \(W\) là bit thứ \(i\) của \(V\).
  2. Thay giá trị hiện tại \(X\) của bản ghi bằng \(X\operatorname{XOR}W\). Tức là, bit thứ \(i\) của giá trị mới bằng \(1\) khi và chỉ khi bit thứ \(i\) của \(X\)\(W\) khác nhau.
  3. Cuối cùng, trả về cho người dùng số bit bằng \(1\) trong giá trị mới.

May mắn là bất kể giá trị ban đầu và các độ xoay mà cơ sở dữ liệu chọn là gì, ta luôn có thể đặt lại bản ghi thành toàn bit \(0\) sau không quá \(300\) lần dùng thao tác này. Hãy viết chương trình tương tác với cơ sở dữ liệu để thực hiện việc đó.

Dữ liệu vào

Ban đầu, chương trình phải đọc một dòng chứa số nguyên \(\mathbf{T}\), là số lượng bộ test. Sau đó phải xử lý \(\mathbf{T}\) bộ test.

Ở đầu mỗi bộ test, bản ghi trong cơ sở dữ liệu được đặt thành một giá trị khác 00000000. Trong mỗi bộ test, chương trình được thực hiện tối đa \(300\) lượt trao đổi.

Sau khi chương trình gửi một giá trị \(V\), nó đọc một dòng chứa số nguyên duy nhất \(\mathbf{N}_i\), là số bit bằng \(1\) trong giá trị bản ghi đã được cập nhật.

Dữ liệu ra

Lượt trao đổi thứ \(i\) bắt đầu bằng việc chương trình in một dòng chứa đúng một chuỗi nhị phân \(8\) bit để dùng làm giá trị \(V\) trong thao tác đã mô tả.

Lời giải được xem là đúng khi và chỉ khi đặt thành công bản ghi về 00000000 trong mọi bộ test.

Giao thức tương tác

Đây là bài tương tác. Bạn cần đọc kỹ phần Interactive Problems trong FAQ của Google Code Jam.

Sau khi bạn in \(V\), giám khảo thực hiện thao tác xoay và XOR rồi gửi \(\mathbf{N}_i\):

  • Nếu \(\mathbf{N}_i=0\), bạn đã thành công và phải bắt đầu bộ test tiếp theo, hoặc kết thúc chương trình nếu đây là bộ test cuối.
  • Nếu \(\mathbf{N}_i=-1\), đây là lượt trao đổi thứ \(300\) của bộ test nhưng bản ghi chưa từng trở thành toàn bit \(0\), nên bộ test thất bại. Không bộ test nào khác được xử lý sau đó.
  • Nếu \(1\le\mathbf{N}_i\le8\), giá trị mới của bản ghi có \(\mathbf{N}_i\) bit \(1\) và bạn có thể tiếp tục lượt trao đổi kế tiếp để cố đưa nó về toàn bit \(0\).

Nếu ở bất kỳ thời điểm nào giám khảo nhận được một dòng sai định dạng hoặc không hợp lệ từ chương trình, giám khảo sẽ in duy nhất số \(-1\) và không in thêm gì nữa. Khi nhận \(-1\), bạn phải kết thúc chương trình đúng cách, không vượt giới hạn tài nguyên, để nhận phán quyết Wrong Answer. Nếu không, bạn sẽ nhận phán quyết tương ứng với tài nguyên bị vượt hoặc điều kiện kết thúc sai.

Ràng buộc

  • \(1\le\mathbf{T}\le100\).
  • \(-1\le\mathbf{N}_i\le8\) với mọi \(i\).

Phân nhóm

  • Test Set 1 (phán quyết hiển thị): Giá trị ban đầu của bản ghi được chọn đều ngẫu nhiên trong tất cả các chuỗi nhị phân \(8\) bit khác 00000000. Mỗi độ xoay cũng được chọn đều ngẫu nhiên và độc lập với mọi lựa chọn cũng như tương tác trước đó.
  • Test Set 2 (phán quyết hiển thị): Giám khảo có tính đối kháng. Điều này có nghĩa là, trong số những khả năng khác, giám khảo có thể thay đổi giá trị ban đầu hoặc các độ xoay miễn chúng vẫn nhất quán với toàn bộ tương tác. Giá trị ban đầu được bảo đảm không bao giờ là 00000000.

Công cụ kiểm thử

Bạn có thể dùng công cụ kiểm thử chính thức để chạy cục bộ hoặc trên nền tảng của Google Code Jam. Khi kiểm thử cục bộ, cần chạy công cụ song song với chương trình; có thể dùng interactive runner của Google. Hãy đọc hướng dẫn trong phần chú thích của tệp đó và phần Interactive Problems trong FAQ để biết thêm chi tiết.

Hướng dẫn dành cho công cụ kiểm thử nằm trong các chú thích bên trong công cụ. Bạn được khuyến khích bổ sung các bộ test của riêng mình. Mặc dù công cụ được thiết kế để mô phỏng hệ thống chấm, nó không phải hệ thống chấm thật và có thể hành xử khác. Nếu chương trình vượt qua công cụ nhưng thất bại trên giám khảo thật, hãy kiểm tra phần Coding trong FAQ để bảo đảm bạn dùng cùng trình biên dịch với hệ thống chấm.

Tải công cụ kiểm thử chính thức.

Ví dụ

Ví dụ tương tác

Giám khảo gửi 1, cho biết có một bộ test. Bản ghi của bộ test này bắt đầu ở giá trị ẩn 10000000.

  1. Lời giải gửi 00110011.
  2. Giám khảo chọn \(r=5\), xoay giá trị đã nhận thành 10011001, rồi tính 10011001 XOR 10000000 để được 00011001, là giá trị mới của bản ghi.
  3. Giám khảo gửi 3, vì 00011001 có ba bit \(1\).
  4. Lời giải gửi 00011001.
  5. Giám khảo chọn \(r=0\) nên đầu vào không bị xoay. Nó trùng với giá trị hiện tại của bản ghi, vì vậy sau XOR bản ghi trở thành 00000000.
  6. Giám khảo gửi 0, báo rằng bản ghi không còn bit \(1\) nào và bộ test đã hoàn tất.

Nguồn

Google Code Jam 2022, Vòng 1B, bài ASeDatAb.

Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.

2. Google Code Jam 2022 - Controlled Inflation

Điểm: 35 Thời gian: 1.0s Bộ nhớ: 1G Input: bàn phím Output: màn hình

Hàng người chờ dùng máy bơm hơi tại trạm xăng của bạn ngày càng dài! Bạn muốn tối ưu quy trình để giúp khách hàng bơm lốp xe, bóng thể thao, các con vật bóng bay khổng lồ trong lễ diễu hành và những sản phẩm khác nhanh hơn.

Máy bơm hoạt động tự động: bạn đặt áp suất thành một số pascal cụ thể rồi nối máy vào sản phẩm cần bơm; máy sẽ bơm sản phẩm đến đúng áp suất đó. Máy chỉ có hai nút: tăng và giảm. Hai nút tương ứng tăng hoặc giảm áp suất mục tiêu đúng \(1\) pascal.

Có một hàng gồm \(\mathbf{N}\) khách hàng, mỗi người mang đúng \(\mathbf{P}\) sản phẩm cần bơm bằng máy. Bạn biết áp suất mục tiêu của từng sản phẩm. Bạn có thể bơm các sản phẩm của cùng một khách theo thứ tự tùy ý, nhưng không được thay đổi thứ tự khách hàng. Cụ thể, phải bơm xong mọi sản phẩm của khách thứ \(i\) trước khi bơm bất kỳ sản phẩm nào của khách thứ \(i+1\). Giữa hai sản phẩm có áp suất mục tiêu khác nhau, bạn phải dùng các nút trên máy để điều chỉnh.

Ban đầu máy bơm được đặt ở \(0\) pascal; sau khi đã bơm tất cả sản phẩm của mọi khách, máy có thể dừng ở bất kỳ giá trị nào. Nếu sắp thứ tự sản phẩm của từng khách một cách tối ưu, số lần nhấn nút ít nhất là bao nhiêu?

Dữ liệu vào

Dòng đầu chứa số lượng bộ test \(\mathbf{T}\). Tiếp theo là \(\mathbf{T}\) bộ test.

Mỗi bộ test bắt đầu bằng một dòng chứa hai số nguyên \(\mathbf{N}\)\(\mathbf{P}\): số khách hàng và số sản phẩm mà mỗi khách mang đến. Tiếp theo là \(\mathbf{N}\) dòng. Dòng thứ \(i\) chứa \(\mathbf{P}\) số nguyên \(\mathbf{X}_{i,1},\mathbf{X}_{i,2},\ldots,\mathbf{X}_{i,\mathbf{P}}\), trong đó \(\mathbf{X}_{i,j}\) là áp suất mục tiêu, tính bằng pascal, của sản phẩm thứ \(j\) mà khách thứ \(i\) mang đến.

Dữ liệu ra

Với mỗi bộ test, in một dòng theo định dạng Case #x: y, trong đó \(x\) là số thứ tự bộ test (bắt đầu từ \(1\)), còn \(y\) là số lần nhấn nút ít nhất để bơm mọi sản phẩm đúng áp suất yêu cầu.

Ràng buộc

  • \(1\le\mathbf{T}\le100\).
  • \(1\le\mathbf{X}_{i,j}\le10^9\) với mọi \(i,j\).

Phân nhóm

  • Test Set 1 (phán quyết hiển thị): \(2\le\mathbf{N}\le10\)\(2\le\mathbf{P}\le3\).
  • Test Set 2 (phán quyết ẩn): \(2\le\mathbf{N}\le1000\)\(2\le\mathbf{P}\le100\).

Điểm các phân nhóm

Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.

Phân nhóm Điểm Google Code Jam Tỷ lệ điểm của bài
Test Set 1 14/35 40%
Test Set 2 21/35 60%

Ví dụ

Ví dụ 1

Input
2
3 3
30 10 40
20 50 60
60 60 50
5 2
1 1000000000
500000000 1000000000
1 1000000000
500000000 1
1 1000000000
Output
Case #1: 110
Case #2: 4999999996
Giải thích

Trong bộ test mẫu số 1, một cách dùng máy bơm tối ưu là:

  1. Nhấn nút tăng \(10\) lần, đưa máy lên \(10\); bơm sản phẩm cần \(10\) pascal của khách thứ nhất.
  2. Nhấn tăng \(30\) lần, đưa máy lên \(40\); bơm sản phẩm cần \(40\) pascal của khách thứ nhất.
  3. Nhấn giảm \(10\) lần, đưa máy xuống \(30\); bơm sản phẩm cần \(30\) pascal của khách thứ nhất.
  4. Nhấn giảm \(10\) lần, đưa máy xuống \(20\); bơm sản phẩm cần \(20\) pascal của khách thứ hai.
  5. Nhấn tăng \(30\) lần, đưa máy lên \(50\); bơm sản phẩm cần \(50\) pascal của khách thứ hai.
  6. Nhấn tăng \(10\) lần, đưa máy lên \(60\); bơm sản phẩm cần \(60\) pascal của khách thứ hai và cả hai sản phẩm cần \(60\) pascal của khách thứ ba.
  7. Cuối cùng, nhấn giảm \(10\) lần, đưa máy xuống \(50\); bơm sản phẩm cần \(50\) pascal của khách thứ ba.

Tổng cộng có \(110\) lần nhấn nút.

Trong bộ test mẫu số 2, lưu ý rằng đáp án có thể lớn hơn \(2^{32}\).

Nguồn

Google Code Jam 2022, Vòng 1B, bài Controlled Inflation.

Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.

3. Google Code Jam 2022 - Pancake Deque

Điểm: 25 Thời gian: 1.5s Bộ nhớ: 1G Input: bàn phím Output: màn hình

Bánh kếp thường được phục vụ theo chồng, nhưng Infinite House of Pancakes luôn đón nhận thay đổi! Điểm quảng cáo mới của nhà hàng là phục vụ bánh kếp từ một deque, tức hàng đợi hai đầu.

Bạn là nhân viên phục vụ của nhà hàng và nhiệm vụ là phục vụ mọi chiếc bánh trong deque. Khách đến lần lượt từng người và mỗi người nhận một chiếc bánh. Với mỗi khách, bạn phải phục vụ chiếc bánh ngoài cùng bên trái hoặc ngoài cùng bên phải của deque; quyền lựa chọn thuộc về bạn. Khi được phục vụ, chiếc bánh biến mất khỏi deque, để lộ chiếc nằm cạnh nó. Khi chỉ còn một chiếc, lựa chọn duy nhất là phục vụ chiếc ấy, rồi công việc hoàn tất.

Mỗi chiếc bánh có một độ ngon. Vì khách hàng không được chọn bánh, một khách chỉ phải trả tiền nếu chiếc bánh họ nhận ngon ít nhất bằng từng chiếctất cả khách trước đó đã nhận. Khách đầu tiên luôn trả tiền vì chưa có khách nào trước đó.

Nếu phục vụ bánh theo thứ tự làm số người trả tiền lớn nhất, có bao nhiêu khách sẽ trả tiền?

Dữ liệu vào

Dòng đầu chứa số lượng bộ test \(\mathbf{T}\). Tiếp theo là \(\mathbf{T}\) bộ test, mỗi bộ được mô tả bằng hai dòng.

Dòng đầu của một bộ test chứa số nguyên \(\mathbf{N}\), là số bánh trong deque. Dòng thứ hai chứa \(\mathbf{N}\) số nguyên \(\mathbf{D}_1,\mathbf{D}_2,\ldots,\mathbf{D}_\mathbf{N}\), trong đó \(\mathbf{D}_i\) là độ ngon của chiếc bánh thứ \(i\) tính từ trái sang trong deque.

Dữ liệu ra

Với mỗi bộ test, in một dòng theo định dạng Case #x: y, trong đó \(x\) là số thứ tự bộ test (bắt đầu từ \(1\)), còn \(y\) là số khách trả tiền khi bạn phục vụ bánh theo một thứ tự tối đa hóa số lượng ấy.

Ràng buộc

  • \(1\le\mathbf{T}\le100\).
  • \(1\le\mathbf{D}_i\le10^6\) với mọi \(i\).

Phân nhóm

  • Test Set 1 (phán quyết hiển thị): \(2\le\mathbf{N}\le20\).
  • Test Set 2 (phán quyết hiển thị): \(2\le\mathbf{N}\le100\).
  • Test Set 3 (phán quyết ẩn): \(2\le\mathbf{N}\le10^5\).

Điểm các phân nhóm

Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.

Phân nhóm Điểm Google Code Jam Tỷ lệ điểm của bài
Test Set 1 7/25 28%
Test Set 2 8/25 32%
Test Set 3 10/25 40%

Ví dụ

Ví dụ 1

Input
4
2
1 5
4
1 4 2 3
5
10 10 10 10 10
4
7 1 3 1000000
Output
Case #1: 2
Case #2: 3
Case #3: 5
Case #4: 2
Giải thích

Trong bộ test mẫu số 1, có hai thứ tự phục vụ. Nếu phục vụ chiếc có độ ngon \(5\) trước, chỉ chiếc ấy được trả tiền. Nếu phục vụ chiếc có độ ngon \(1\) trước, cả hai đều được trả tiền.

Bộ test mẫu số 2 chính là hình trong đề. Sau đây là mọi thứ tự phục vụ có thể, ghi theo độ ngon; các số được gạch chân là những chiếc mà khách phải trả tiền:

  • \(\underline{1},\underline{4},2,3\)
  • \(\underline{1},\underline{4},3,2\)
  • \(\underline{1},\underline{3},\underline{4},2\)
  • \(\underline{1},\underline{3},2,\underline{4}\)
  • \(\underline{3},1,\underline{4},2\)
  • \(\underline{3},1,2,\underline{4}\)
  • \(\underline{3},2,1,\underline{4}\)
  • \(\underline{3},2,\underline{4},1\)

Có những thứ tự khiến \(3\) chiếc bánh được trả tiền, nhưng không có thứ tự nào khiến cả \(4\) chiếc đều được trả tiền.

Trong bộ test mẫu số 3, mọi chiếc bánh đều được trả tiền bất kể thứ tự phục vụ.

Trong bộ test mẫu số 4, dù phục vụ chiếc nào trước, hai chiếc ở giữa cũng không bao giờ được trả tiền. Cách tốt nhất là phục vụ chiếc có độ ngon \(7\) trước chiếc có độ ngon \(1000000\).

Nguồn

Google Code Jam 2022, Vòng 1B, bài Pancake Deque.

Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.