import math
from decimal import Decimal
BIG_BUT_NOT_INFINITE = 1e30
F = 100
H = 80
def solve(F, H, pr_h=.5, eps=1e-6):
# X(f, h) := expected number of flips to win given we need h heads out of f
# flips and optimal strategy
# X(f, h) := { 0 if h = 0
# { X(F, H) if f < h
# { min( otherwise
# 1 + X(f-1, h-1) * Pr(h) + X(f-1, h) * (1 - Pr(h)),
# X(F, H)
# )
#
# X(f, h) depends on X(F, H) so it can't be computed.
# So introduce X_est(F, H) as a guess for X(F, H).
# And introduce X_conv(f, h) which is X(f, h) but it uses X_est(F, H)
# instead of X(F, H) in the definition above.
#
# If X_est(F, H) <= X(F, H), then X_conv(F, H) = X_est(F, H).
# This is because it will just "restart" and return X_est(F, H) immediately.
# So we can find the largest value of X_est(F, H) for which X_conv(F, H) != X_est(F, H).
# That should be the correct value of X_est(F, H).
pr_h_d = Decimal(pr_h)
eps_d = Decimal(eps)
def x_conv(x_est):
cache = {}
def x(f, h):
if h == 0: return 0
if f < h: return x_est
cache_key = (f, h)
if cache_key not in cache:
do_flip = 1 + x(f-1, h-1) * pr_h_d + x(f-1, h) * (1 - pr_h_d)
cache[cache_key] = min(do_flip, x_est)
return cache[cache_key]
return x
lo = Decimal(H)
hi = Decimal(BIG_BUT_NOT_INFINITE)
while hi - lo > eps_d:
x_est_guess = (lo + hi) / Decimal(2)
x_conv_guess = x_conv(x_est_guess)(F, H)
if x_conv_guess == x_est_guess:
lo = x_est_guess
else:
hi = x_est_guess
return x_conv(lo)
oracle = solve(F, H)
# How many flips at the start of the game?
print(oracle(F, H))
print(oracle(2, 2))
print(oracle(20, 20))
print(oracle(40, 40))
aW1wb3J0IG1hdGgKZnJvbSBkZWNpbWFsIGltcG9ydCBEZWNpbWFsCgpCSUdfQlVUX05PVF9JTkZJTklURSA9IDFlMzAKRiA9IDEwMApIID0gODAKCmRlZiBzb2x2ZShGLCBILCBwcl9oPS41LCBlcHM9MWUtNik6CiAgIyBYKGYsIGgpIDo9IGV4cGVjdGVkIG51bWJlciBvZiBmbGlwcyB0byB3aW4gZ2l2ZW4gd2UgbmVlZCBoIGhlYWRzIG91dCBvZiBmCiAgIyAgICAgICAgICAgIGZsaXBzIGFuZCBvcHRpbWFsIHN0cmF0ZWd5CiAgIyBYKGYsIGgpIDo9IHsgMCAgICAgICAgICAgICBpZiBoID0gMAogICMgICAgICAgICAgICB7IFgoRiwgSCkgICAgICAgaWYgZiA8IGgKICAjICAgICAgICAgICAgeyBtaW4oICAgICAgICAgIG90aGVyd2lzZQogICMgICAgICAgICAgICAgICAgMSArIFgoZi0xLCBoLTEpICogUHIoaCkgKyBYKGYtMSwgaCkgKiAoMSAtIFByKGgpKSwKICAjICAgICAgICAgICAgICAgIFgoRiwgSCkKICAjICAgICAgICAgICAgICApCiAgIwogICMgWChmLCBoKSBkZXBlbmRzIG9uIFgoRiwgSCkgc28gaXQgY2FuJ3QgYmUgY29tcHV0ZWQuCiAgIyBTbyBpbnRyb2R1Y2UgWF9lc3QoRiwgSCkgYXMgYSBndWVzcyBmb3IgWChGLCBIKS4KICAjIEFuZCBpbnRyb2R1Y2UgWF9jb252KGYsIGgpIHdoaWNoIGlzIFgoZiwgaCkgYnV0IGl0IHVzZXMgWF9lc3QoRiwgSCkKICAjIGluc3RlYWQgb2YgWChGLCBIKSBpbiB0aGUgZGVmaW5pdGlvbiBhYm92ZS4KICAjCiAgIyBJZiBYX2VzdChGLCBIKSA8PSBYKEYsIEgpLCB0aGVuIFhfY29udihGLCBIKSA9IFhfZXN0KEYsIEgpLgogICMgVGhpcyBpcyBiZWNhdXNlIGl0IHdpbGwganVzdCAicmVzdGFydCIgYW5kIHJldHVybiBYX2VzdChGLCBIKSBpbW1lZGlhdGVseS4KICAjIFNvIHdlIGNhbiBmaW5kIHRoZSBsYXJnZXN0IHZhbHVlIG9mIFhfZXN0KEYsIEgpIGZvciB3aGljaCBYX2NvbnYoRiwgSCkgIT0gWF9lc3QoRiwgSCkuCiAgIyBUaGF0IHNob3VsZCBiZSB0aGUgY29ycmVjdCB2YWx1ZSBvZiBYX2VzdChGLCBIKS4KCiAgcHJfaF9kID0gRGVjaW1hbChwcl9oKQogIGVwc19kID0gRGVjaW1hbChlcHMpCgogIGRlZiB4X2NvbnYoeF9lc3QpOgogICAgY2FjaGUgPSB7fQogICAgZGVmIHgoZiwgaCk6CiAgICAgIGlmIGggPT0gMDogcmV0dXJuIDAKICAgICAgaWYgZiA8IGg6IHJldHVybiB4X2VzdAogICAgICAKICAgICAgY2FjaGVfa2V5ID0gKGYsIGgpCiAgICAgIGlmIGNhY2hlX2tleSBub3QgaW4gY2FjaGU6CiAgICAgICAgZG9fZmxpcCA9IDEgKyB4KGYtMSwgaC0xKSAqIHByX2hfZCArIHgoZi0xLCBoKSAqICgxIC0gcHJfaF9kKQogICAgICAgIGNhY2hlW2NhY2hlX2tleV0gPSBtaW4oZG9fZmxpcCwgeF9lc3QpCiAgICAgIHJldHVybiBjYWNoZVtjYWNoZV9rZXldCiAgICByZXR1cm4geAogIAogIGxvID0gRGVjaW1hbChIKQogIGhpID0gRGVjaW1hbChCSUdfQlVUX05PVF9JTkZJTklURSkKICB3aGlsZSBoaSAtIGxvID4gZXBzX2Q6CiAgICB4X2VzdF9ndWVzcyA9IChsbyArIGhpKSAvIERlY2ltYWwoMikKICAgIHhfY29udl9ndWVzcyA9IHhfY29udih4X2VzdF9ndWVzcykoRiwgSCkKICAgIGlmIHhfY29udl9ndWVzcyA9PSB4X2VzdF9ndWVzczoKICAgICAgbG8gPSB4X2VzdF9ndWVzcwogICAgZWxzZToKICAgICAgaGkgPSB4X2VzdF9ndWVzcwogIAogIHJldHVybiB4X2NvbnYobG8pCgpvcmFjbGUgPSBzb2x2ZShGLCBIKQoKIyBIb3cgbWFueSBmbGlwcyBhdCB0aGUgc3RhcnQgb2YgdGhlIGdhbWU/CnByaW50KG9yYWNsZShGLCBIKSkKcHJpbnQob3JhY2xlKDIsIDIpKQpwcmludChvcmFjbGUoMjAsIDIwKSkKcHJpbnQob3JhY2xlKDQwLCA0MCkpCg==