IOI17 Coins

14-10-2022

Abridged Problem Statement

Problem statement

มีคนสองคนและตารางขนาด 8×88 \times 8 โดยแต่ละช่องของตารางจะมีเหรียญอยู่ช่องละ 1 เหรียญ และแต่ละเหรียญจะมีชื่อตั้งแต่ 00 ถึง 6363 โดยเรียงตามลำดับจากซ้ายไปขวา และจากบนลงล่าง

0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263\begin{array}{|c|c|c|c|c|c|c|c|} \hline 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ \hline 8 & 9 & 10 & 11 & 12 & 13 & 14 & 15 \\ \hline 16 & 17 & 18 & 19 & 20 & 21 & 22 & 23 \\ \hline 24 & 25 & 26 & 27 & 28 & 29 & 30 & 31 \\ \hline 32 & 33 & 34 & 35 & 36 & 37 & 38 & 39 \\ \hline 40 & 41 & 42 & 43 & 44 & 45 & 46 & 47 \\ \hline 48 & 49 & 50 & 51 & 52 & 53 & 54 & 55 \\ \hline 56 & 57 & 58 & 59 & 60 & 61 & 62 & 63 \\ \hline \end{array}
ตารางขนาด 8×88 \times 8

โดยในตอนแรกแต่ละเหรียญจะเป็นหัวหรือก้อยตาม std::vector<int> b ที่ได้รับมา
มี 1 คนที่รู้ว่าเเหรียญที่ต้องการหาคือเหรียญ cc แต่ทว่าในการหาเหรียญ cc นั้นคนที่จะตอบ(อีกคนหนึ่ง)ก็จะไม่รู้ว่าเหรียญ cc คือเหรียญหมายเลขใด

งานของคุณ ช่วยคิดวิธีทำให้คนที่ไม่รู้ว่าเหรียญ cc สามารถรู้ได้ว่าเหรียญ cc คือเหรียญใดโดยคนที่รู้ว่าเหรียญ cc คือเหรียนไหนพลิกเหรียญได้ไม่เกิน kk ครั้ง

ปัญหาย่อย c<0,k=1c < 0, k = 1

ในกรณีนี้สามารถแก้ได้โดย

  1. ถ้า c=0c=0 ให้พลิกเหรียญหมายเลข 00 เป็น 00 ได้โดยพลิกไม่เกิน 11 ครั้ง
  2. ถ้า c=1c=1 ให้พลิกเหรียญหมายเลข 00 เป็น 11 ได้โดยพลิกไม่เกิน 11 ครั้ง

ปัญหาย่อย k=64k=64

พลิกเหรียญทั้งหมดที่ไม่ใช่ cc ให้เป็น 00 และทำให้เหรียญ cc เป็น 11 ทำได้ในการพลิกไม่เกิน 6464 ครั้ง

ปัญหาย่อย k=8k=8

แปลงตารางช่อง 0,1,,70,1,\dots,7 ให้เป็นเลขฐานสอง ของ cc ทำทำได้ในการพลิกไม่เกิน 88 ครั้ง

ปัญหาเต็ม k=1k=1

นำหมายเลขของเหรียญที่พลิกเป็นหน้า 11 มา \oplus (Binary XOR) กันได้ zz* แล้วพลิกเหรียญหมายเลข czc \oplus z* ทำให้พลิกเพียง 11 ครั้งเท่านั้น

เมื่ออีกคนมาหาหมายเลข cc ก็สามารถนำหมายเลขของเหรียญที่มีค่าเป็น 11 มา \oplus กันเพื่อหาเหรียญ cc ได้เลย

โดยการทำวิธีการนี้อาศัยสมบัติของ \oplus คือ

ab=cca=b\begin{aligned} a \oplus b &= c\\ c \oplus a &= b \end{aligned}

Solution Code