from random import *
seed(674354267)
player_string = input()
player = (1 if player_string[0] == 'A' else 0)
n, t = map(int,input().split())
hashes = [[randint(0,1) for i in range(n)] for j in range(2)]
moves = "PKN" # paper rock scissors
for _ in range(t):
my_string = input()
my_string = ''.join(chr(ord(my_string[i])^hashes[player][i]) for i in range(n))
my_val = int(my_string,2)
lo, hi = 0, (1<<n)-1
mylo, myhi = 0, (1<<n)-1
while lo < hi or mylo < myhi:
mid1 = (lo*2+hi)//3
mid2 = (lo+hi*2)//3
mymid1 = (mylo*2+myhi)//3
mymid2 = (mylo+myhi*2)//3
mymove = (0 if my_val <= mymid1 else (1 if my_val <= mymid2 else 2))
print(moves[mymove])
opmove = input()
opmove = moves.find(opmove)
if (opmove == 0):
hi = mid1
elif (opmove == 1):
lo = mid1 + 1
hi = mid2
else:
lo = mid2 + 1
if (mymove == 0):
myhi = mymid1
elif (mymove == 1):
mylo = mymid1 + 1
myhi = mymid2
else:
mylo = mymid2 + 1
# maybe add early breaks
if (opmove == (mymove + 1) % 3):
# we have to lose, always print 1
while lo < hi or mylo < myhi: # this early breaks just in case its close
print(moves[1])
opmove = input()
opmove = moves.find(opmove)
split = (lo * 6 + hi * 19)//25
if (opmove == 0):
hi = split
break
else:
lo = split + 1
# best split so far : ~ 2 5 7
elif (opmove == (mymove + 2) % 3):
# we have to win, print 0 often, 1 less often
while lo < hi or mylo < myhi:
split = (mylo * 6 + myhi * 19)//25
mymove = (0 if my_val <= split else 1)
print(moves[mymove])
opmove = input()
if (mymove == 0):
myhi = split
break
else:
mylo = split + 1
op_string = bin(lo)[2:]
op_string = "0" * (n - len(op_string)) + op_string
ans = ''.join(chr(ord(op_string[i])^hashes[1-player][i]) for i in range(n))
print("! " + ans)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | from random import * seed(674354267) player_string = input() player = (1 if player_string[0] == 'A' else 0) n, t = map(int,input().split()) hashes = [[randint(0,1) for i in range(n)] for j in range(2)] moves = "PKN" # paper rock scissors for _ in range(t): my_string = input() my_string = ''.join(chr(ord(my_string[i])^hashes[player][i]) for i in range(n)) my_val = int(my_string,2) lo, hi = 0, (1<<n)-1 mylo, myhi = 0, (1<<n)-1 while lo < hi or mylo < myhi: mid1 = (lo*2+hi)//3 mid2 = (lo+hi*2)//3 mymid1 = (mylo*2+myhi)//3 mymid2 = (mylo+myhi*2)//3 mymove = (0 if my_val <= mymid1 else (1 if my_val <= mymid2 else 2)) print(moves[mymove]) opmove = input() opmove = moves.find(opmove) if (opmove == 0): hi = mid1 elif (opmove == 1): lo = mid1 + 1 hi = mid2 else: lo = mid2 + 1 if (mymove == 0): myhi = mymid1 elif (mymove == 1): mylo = mymid1 + 1 myhi = mymid2 else: mylo = mymid2 + 1 # maybe add early breaks if (opmove == (mymove + 1) % 3): # we have to lose, always print 1 while lo < hi or mylo < myhi: # this early breaks just in case its close print(moves[1]) opmove = input() opmove = moves.find(opmove) split = (lo * 6 + hi * 19)//25 if (opmove == 0): hi = split break else: lo = split + 1 # best split so far : ~ 2 5 7 elif (opmove == (mymove + 2) % 3): # we have to win, print 0 often, 1 less often while lo < hi or mylo < myhi: split = (mylo * 6 + myhi * 19)//25 mymove = (0 if my_val <= split else 1) print(moves[mymove]) opmove = input() if (mymove == 0): myhi = split break else: mylo = split + 1 op_string = bin(lo)[2:] op_string = "0" * (n - len(op_string)) + op_string ans = ''.join(chr(ord(op_string[i])^hashes[1-player][i]) for i in range(n)) print("! " + ans) |
English