import random
from Queue import Queue
class Pow:
def __init__(self, base, exp):
self.base = base
self.exp = exp
class Pair:
def __init__(self, x, y):
self.x = x
self.y = y
def gcd(a, b):
while b: a, b = b, a % b
return a
def rabin_miller(p):
if p < 2: return False
if p != 2 and p % 2 == 0: return False
s = p - 1
while s % 2 == 0: s >>= 1
for i in xrange(10):
a = random.randrange(p - 1) + 1
temp = s
mod = pow(a, temp, p)
while temp != p-1 and mod != 1 and mod != p-1:
mod = (mod * mod) % p
temp = temp * 2
if mod != p-1 and temp % 2 == 0:
return False
return True
def brent(n):
if n % 2 == 0: return 2;
x, c, m = random.randrange(0,n), random.randrange(1,n), random.randrange(1,n)
y, r, q = x, 1, 1
g, ys = 0, 0
while True:
x = y
for i in range(r):
y, k = (y*y+c)%n, 0
while True:
ys = y
for i in range(min(m,r-k)):
y, q = (y*y+c)%n, q*abs(x-y)%n
g, k = gcd(q,n), k+m
if k >= r or g > 1: break
r = 2 * r
if g > 1: break
if g == n:
while True :
ys, g = (x*x+c)%n, gcd(abs(x-ys),n)
if g > 1: break
return g
def pollard(n):
if n % 2 == 0:
return 2;
x = random.randrange(2,1000000)
c = random.randrange(2,1000000)
y = x
d = 1
while d == 1:
x = (x * x + c) % n
y = (y * y + c) % n
y = (y * y + c) % n
d = gcd(x - y, n)
if d == n:
break
return d
# Prime Factorization by Pollard Rho alrorithm
# http://c...content-available-to-author-only...e.com/recipes/577037-pollard-rho-prime-factorization/
def factor(n):
q1 = Queue()
q2 = []
q1.put(n)
while not q1.empty():
l = q1.get()
if rabin_miller(l):
q2.append(l)
continue
d = pollard(l)
if d == l: q1.put(l)
else:
q1.put(d)
q1.put(l / d)
return q2
# Square root of n in integer.
def sqrt(n):
if n <= 0: return 0
s = 1
t = n;
while s < t:
s <<= 1
t >>= 1
while True:
t = s
s = (n / s + s) >> 1
if s >= t: break
return t
# Return (a|n).
# (a|n) = 0 if a = 0 (mod p)
# = +1 if x^2 = a (mod p) for some x
# = -1 if there is no such x
def jacobi(a, n):
t = 1
while a != 0:
while a % 2 == 0:
a = a / 2
if n % 8 == 3 or n % 8 == 5: t = -t
(a, n) = (n, a)
if a % 4 == 3 and n % 4 == 3: t = -t
a = a % n
if n == 1: return t
return 0
# Return a^n (mod p)
def pow_mod(a, n, p):
if n == 0: return 1
if n % 2 == 0: return pow_mod(a * a % p, n / 2, p)
return a * pow_mod( a, n - 1, p ) % p
# Find x who satisfies x*x=n (mod prime p) by Shanks-Tonelli algorithm.
# http://w...content-available-to-author-only...x.com/wiki/Shanks-Tonelli_algorithm
def mod_sqrt_by_shanks_tonelli(prime, arg):
y = 2
result = 0
r = 0
q = prime - 1
if jacobi(arg, prime) == -1: return -1
while jacobi(y, prime) != -1: y += 1
result = prime - 1
while q % 2 == 0:
r += 1
q /= 2
result >>= r
y = pow_mod(y, result, prime)
result >>= 1
b = pow_mod(arg, result, prime)
result = arg * b
result %= prime
b *= result
b %= prime
while b != 1:
t = b * b
t %= prime
m = 1
while t != 1:
t *= t
t %= prime
m += 1
t = 0
t |= (1 << (r-m-1))
t %= prime
y %= prime
t = pow_mod(y, t, prime)
y = t * t
r = m
result *= t
result %= prime
b *= y % prime
b %= prime
return result
# Express prime p as a sum of squared two integers, based on Serret's algorithm.
# See p.122 of "The higher arithmetic: an introduction to the theory of numbers".
def square_sum_of_prime_by_serret(p):
if p == 2: return Pair(1, 1)
if p % 4 != 1: return None
q = Pair(p, mod_sqrt_by_shanks_tonelli(p, p - 1))
if 2 * q.y >= p: q.y = p - q.y
v = []
while q.y > 0:
v.append(q.x / q.y)
q.x, q.y = q.y, q.x - (q.x / q.y) * q.y
q.x = v[len(v) / 2]
q.y = 1
for i in range(len(v)/2+1, len(v)):
q.x, q.y = v[i] * q.x + q.y, q.x
if 2 * q.x >= p:
q.x = p - q.x
q.y = sqrt(p - q.x * q.x)
if q.y < q.x:
q.x, q.y = q.y, q.x
return q
def expand(a, b, c, d, u):
q = Pair(0, a * d + b * c)
if a * c >= b * d:
q.x = a * c - b * d
else:
q.x = b * d - a * c
if q.y < q.x:
q.x, q.y = q.y, q.x
for p in u:
if p.x == q.x: return False
u.append(q)
return u
# Find all pairs x>0 and y>0 which satisfy x^2+y^2=n (x<y).
# n is the form of exponent expression.
def square_sum_of_integer(v):
n = 0
u, v1, v2 = [], [], []
for p in v:
if p.base == 2 or p.base % 4 == 1:
for i in range(p.exp): v1.append(p.base)
n += p.exp
else:
if p.exp % 2 != 0: return False
for i in range(p.exp / 2): v2.append(p.base)
if len(v1) == 0:
q = Pair(1, 0)
for p in v:
for i in range(p.exp): q.x *= p.base
u.append(q)
return false
w = []
r = square_sum_of_prime_by_serret(v1[0])
if r == None:
r.x = r.y = v1[0]
u.append(r)
for i in range(1, len(v1)):
r = square_sum_of_prime_by_serret(v1[i])
if r != None:
for q in u:
w = expand(q.x, q.y, r.x, r.y, w)
w = expand(q.x, q.y, r.y, r.x, w)
u, w = w, u
w = []
for i in range(1, len(v2)):
for q in u:
q.x *= v2[i]
q.y *= v2[i]
return u
def solve(n):
r = 0
t = 10**(n/2)
v = []
u = []
m = t*t + 1
p = factor(m)
p.sort()
q = Pow(p[0], 1)
for i in range(1, len(p)):
if p[i] != p[i-1]:
v.append(q)
q = Pow(p[i], 1)
else: q.exp += 1
v.append(q)
u = square_sum_of_integer(v)
for s in u:
if s.x % 2 != 0: s.x, s.y = s.y, s.x
x = t / 2 + s.x / 2
y = (1 + s.y) / 2
if x >= t / 10 and x < t and y < t:
# print " " + str(t * x + y)
r += t * x + y
x = t / 2 - s.x / 2
if x >= t / 10 and x < t and y < t:
# print " " + str(t * x + y)
r += t * x + y
print str(n) + ': ' + str(r)
for n in range(2, 38, 2):
solve(n)
solve(68)
aW1wb3J0IHJhbmRvbQpmcm9tIFF1ZXVlIGltcG9ydCBRdWV1ZQoKY2xhc3MgUG93OgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGJhc2UsIGV4cCk6CiAgICAgICAgc2VsZi5iYXNlID0gYmFzZQogICAgICAgIHNlbGYuZXhwID0gZXhwCgpjbGFzcyBQYWlyOgogICAgZGVmIF9faW5pdF9fKHNlbGYsIHgsIHkpOgogICAgICAgIHNlbGYueCA9IHgKICAgICAgICBzZWxmLnkgPSB5CgpkZWYgZ2NkKGEsIGIpOgogICAgd2hpbGUgYjogYSwgYiA9IGIsIGEgJSBiCiAgICByZXR1cm4gYQoKZGVmIHJhYmluX21pbGxlcihwKToKCWlmIHAgPCAyOiByZXR1cm4gRmFsc2UKCWlmIHAgIT0gMiBhbmQgcCAlIDIgPT0gMDogcmV0dXJuIEZhbHNlCglzID0gcCAtIDEKCXdoaWxlIHMgJSAyID09IDA6IHMgPj49IDEKCWZvciBpIGluIHhyYW5nZSgxMCk6CgkJYSA9IHJhbmRvbS5yYW5kcmFuZ2UocCAtIDEpICsgMQoJCXRlbXAgPSBzCgkJbW9kID0gcG93KGEsIHRlbXAsIHApCgkJd2hpbGUgdGVtcCAhPSBwLTEgYW5kIG1vZCAhPSAxIGFuZCBtb2QgIT0gcC0xOgoJCQltb2QgPSAobW9kICogbW9kKSAlIHAKCQkJdGVtcCA9IHRlbXAgKiAyCgkJaWYgbW9kICE9IHAtMSBhbmQgdGVtcCAlIDIgPT0gMDoKCQkJcmV0dXJuIEZhbHNlCglyZXR1cm4gVHJ1ZQoKZGVmIGJyZW50KG4pOgogICAgaWYgbiAlIDIgPT0gMDogcmV0dXJuIDI7CiAgICB4LCBjLCBtID0gcmFuZG9tLnJhbmRyYW5nZSgwLG4pLCByYW5kb20ucmFuZHJhbmdlKDEsbiksIHJhbmRvbS5yYW5kcmFuZ2UoMSxuKQogICAgeSwgciwgcSA9IHgsIDEsIDEKICAgIGcsIHlzID0gMCwgMAogICAgd2hpbGUgVHJ1ZToKICAgICAgICB4ID0geQogICAgICAgIGZvciBpIGluIHJhbmdlKHIpOgogICAgICAgICAgICB5LCBrID0gKHkqeStjKSVuLCAwCiAgICAgICAgd2hpbGUgVHJ1ZToKICAgICAgICAgICAgeXMgPSB5CiAgICAgICAgICAgIGZvciBpIGluIHJhbmdlKG1pbihtLHItaykpOgogICAgICAgICAgICAgICAgeSwgcSA9ICh5KnkrYyklbiwgcSphYnMoeC15KSVuCiAgICAgICAgICAgIGcsIGsgPSBnY2QocSxuKSwgayttCiAgICAgICAgICAgIGlmIGsgPj0gciBvciBnID4gMTogYnJlYWsKICAgICAgICByID0gMiAqIHIKICAgICAgICBpZiBnID4gMTogYnJlYWsKICAgIGlmIGcgPT0gbjoKICAgICAgICB3aGlsZSBUcnVlIDoKICAgICAgICAgICAgeXMsIGcgPSAoeCp4K2MpJW4sIGdjZChhYnMoeC15cyksbikKICAgICAgICAgICAgaWYgZyA+IDE6IGJyZWFrCiAgICByZXR1cm4gZwoKZGVmIHBvbGxhcmQobik6CiAgICBpZiBuICUgMiA9PSAwOgogICAgICAgIHJldHVybiAyOwogICAgeCA9IHJhbmRvbS5yYW5kcmFuZ2UoMiwxMDAwMDAwKQogICAgYyA9IHJhbmRvbS5yYW5kcmFuZ2UoMiwxMDAwMDAwKQogICAgeSA9IHgKICAgIGQgPSAxCiAgICB3aGlsZSBkID09IDE6CiAgICAgICAgeCA9ICh4ICogeCArIGMpICUgbgogICAgICAgIHkgPSAoeSAqIHkgKyBjKSAlIG4KICAgICAgICB5ID0gKHkgKiB5ICsgYykgJSBuCiAgICAgICAgZCA9IGdjZCh4IC0geSwgbikKICAgICAgICBpZiBkID09IG46CiAgICAgICAgICAgIGJyZWFrCiAgICByZXR1cm4gZAoKIyAgICBQcmltZSBGYWN0b3JpemF0aW9uIGJ5IFBvbGxhcmQgUmhvIGFscm9yaXRobQojICAgIGh0dHA6Ly9jLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5lLmNvbS9yZWNpcGVzLzU3NzAzNy1wb2xsYXJkLXJoby1wcmltZS1mYWN0b3JpemF0aW9uLwpkZWYgZmFjdG9yKG4pOgogICAgcTEgPSBRdWV1ZSgpCiAgICBxMiA9IFtdCiAgICBxMS5wdXQobikKICAgIHdoaWxlIG5vdCBxMS5lbXB0eSgpOgogICAgICAgIGwgPSBxMS5nZXQoKQogICAgICAgIGlmIHJhYmluX21pbGxlcihsKToKICAgICAgICAgICAgcTIuYXBwZW5kKGwpCiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgZCA9IHBvbGxhcmQobCkKICAgICAgICBpZiBkID09IGw6IHExLnB1dChsKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHExLnB1dChkKQogICAgICAgICAgICBxMS5wdXQobCAvIGQpCiAgICByZXR1cm4gcTIKCiMgICBTcXVhcmUgcm9vdCBvZiBuIGluIGludGVnZXIuCmRlZiBzcXJ0KG4pOgogICAgaWYgbiA8PSAwOiByZXR1cm4gMAogICAgcyA9IDEKICAgIHQgPSBuOwogICAgd2hpbGUgcyA8IHQ6CiAgICAgICAgcyA8PD0gMQogICAgICAgIHQgPj49IDEKICAgIHdoaWxlIFRydWU6CiAgICAgICAgdCA9IHMKICAgICAgICBzID0gKG4gLyBzICsgcykgPj4gMQogICAgICAgIGlmIHMgPj0gdDogYnJlYWsKICAgIHJldHVybiB0CgojICAgIFJldHVybiAoYXxuKS4KIyAgICAoYXxuKSA9IDAgIGlmIGEgPSAwIChtb2QgcCkKIyAgICAgICAgICA9ICsxIGlmIHheMiA9IGEgKG1vZCBwKSBmb3Igc29tZSB4CiMgICAgICAgICAgPSAtMSBpZiB0aGVyZSBpcyBubyBzdWNoIHgKZGVmIGphY29iaShhLCBuKToKICAgIHQgPSAxCiAgICB3aGlsZSBhICE9IDA6CiAgICAgICAgd2hpbGUgYSAlIDIgPT0gMDoKICAgICAgICAgICAgYSA9IGEgLyAyCiAgICAgICAgICAgIGlmIG4gJSA4ID09IDMgb3IgbiAlIDggPT0gNTogdCA9IC10CiAgICAgICAgKGEsIG4pID0gKG4sIGEpCiAgICAgICAgaWYgYSAlIDQgPT0gMyBhbmQgbiAlIDQgPT0gMzogdCA9IC10CiAgICAgICAgYSA9IGEgJSBuCiAgICBpZiBuID09IDE6IHJldHVybiB0CiAgICByZXR1cm4gMAoKIyAgICBSZXR1cm4gYV5uIChtb2QgcCkKZGVmIHBvd19tb2QoYSwgbiwgcCk6IAogICAgaWYgbiA9PSAwOiByZXR1cm4gMQogICAgaWYgbiAlIDIgPT0gMDogcmV0dXJuIHBvd19tb2QoYSAqIGEgJSBwLCBuIC8gMiwgcCkKICAgIHJldHVybiBhICogcG93X21vZCggYSwgbiAtIDEsIHAgKSAlIHAKCiMgICAgRmluZCB4IHdobyBzYXRpc2ZpZXMgeCp4PW4gKG1vZCBwcmltZSBwKSBieSBTaGFua3MtVG9uZWxsaSBhbGdvcml0aG0uCiMgICAgaHR0cDovL3cuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLnguY29tL3dpa2kvU2hhbmtzLVRvbmVsbGlfYWxnb3JpdGhtCmRlZiBtb2Rfc3FydF9ieV9zaGFua3NfdG9uZWxsaShwcmltZSwgYXJnKToKICAgIHkgPSAyCiAgICByZXN1bHQgPSAwCiAgICByID0gMAogICAgcSA9IHByaW1lIC0gMQogICAgaWYgamFjb2JpKGFyZywgcHJpbWUpID09IC0xOiByZXR1cm4gLTEKICAgIHdoaWxlIGphY29iaSh5LCBwcmltZSkgIT0gLTE6IHkgKz0gMQogICAgcmVzdWx0ID0gcHJpbWUgLSAxCiAgICB3aGlsZSBxICUgMiA9PSAwOgogICAgICAgIHIgKz0gMQogICAgICAgIHEgLz0gMgogICAgcmVzdWx0ID4+PSByCiAgICB5ID0gcG93X21vZCh5LCByZXN1bHQsIHByaW1lKQogICAgcmVzdWx0ID4+PSAxCiAgICBiID0gcG93X21vZChhcmcsIHJlc3VsdCwgcHJpbWUpCiAgICByZXN1bHQgPSBhcmcgKiBiCiAgICByZXN1bHQgJT0gcHJpbWUKICAgIGIgKj0gcmVzdWx0CiAgICBiICU9IHByaW1lCiAgICB3aGlsZSBiICE9IDE6ICAgCiAgICAgICAgdCA9IGIgKiBiCiAgICAgICAgdCAlPSBwcmltZQogICAgICAgIG0gPSAxCiAgICAgICAgd2hpbGUgdCAhPSAxOgogICAgICAgICAgICB0ICo9IHQKICAgICAgICAgICAgdCAlPSBwcmltZQogICAgICAgICAgICBtICs9IDEKICAgICAgICB0ID0gMAogICAgICAgIHQgfD0gKDEgPDwgKHItbS0xKSkKICAgICAgICB0ICU9IHByaW1lCiAgICAgICAgeSAlPSBwcmltZQogICAgICAgIHQgPSBwb3dfbW9kKHksIHQsIHByaW1lKQogICAgICAgIHkgPSB0ICogdAogICAgICAgIHIgPSBtCiAgICAgICAgcmVzdWx0ICo9IHQKICAgICAgICByZXN1bHQgJT0gcHJpbWUKICAgICAgICBiICo9IHkgJSBwcmltZQogICAgICAgIGIgJT0gcHJpbWUKICAgIHJldHVybiByZXN1bHQKCiMgICAgRXhwcmVzcyBwcmltZSBwIGFzIGEgc3VtIG9mIHNxdWFyZWQgdHdvIGludGVnZXJzLCBiYXNlZCBvbiBTZXJyZXQncyBhbGdvcml0aG0uCiMgICAgU2VlIHAuMTIyIG9mICJUaGUgaGlnaGVyIGFyaXRobWV0aWM6IGFuIGludHJvZHVjdGlvbiB0byB0aGUgdGhlb3J5IG9mIG51bWJlcnMiLgpkZWYgc3F1YXJlX3N1bV9vZl9wcmltZV9ieV9zZXJyZXQocCk6CiAgICBpZiBwID09IDI6IHJldHVybiBQYWlyKDEsIDEpCiAgICBpZiBwICUgNCAhPSAxOiByZXR1cm4gTm9uZQogICAgcSA9IFBhaXIocCwgbW9kX3NxcnRfYnlfc2hhbmtzX3RvbmVsbGkocCwgcCAtIDEpKQogICAgaWYgMiAqIHEueSA+PSBwOiBxLnkgPSBwIC0gcS55CiAgICB2ID0gW10KICAgIHdoaWxlIHEueSA+IDA6IAogICAgICAgIHYuYXBwZW5kKHEueCAvIHEueSkKICAgICAgICBxLngsIHEueSA9IHEueSwgcS54IC0gKHEueCAvIHEueSkgKiBxLnkKICAgIHEueCA9IHZbbGVuKHYpIC8gMl0KICAgIHEueSA9IDEKICAgIGZvciBpIGluIHJhbmdlKGxlbih2KS8yKzEsIGxlbih2KSk6CiAgICAgICAgcS54LCBxLnkgPSB2W2ldICogcS54ICsgcS55LCBxLngKICAgIGlmIDIgKiBxLnggPj0gcDoKICAgICAgICBxLnggPSBwIC0gcS54CiAgICBxLnkgPSBzcXJ0KHAgLSBxLnggKiBxLngpCiAgICBpZiBxLnkgPCBxLng6CiAgICAgICAgcS54LCBxLnkgPSBxLnksIHEueAogICAgcmV0dXJuIHEKCmRlZiBleHBhbmQoYSwgYiwgYywgZCwgdSk6CiAgICBxID0gUGFpcigwLCBhICogZCArIGIgKiBjKQogICAgaWYgYSAqIGMgPj0gYiAqIGQ6CiAgICAgICAgcS54ID0gYSAqIGMgLSBiICogZAogICAgZWxzZToKICAgICAgICBxLnggPSBiICogZCAtIGEgKiBjCiAgICBpZiBxLnkgPCBxLng6CiAgICAgICAgcS54LCBxLnkgPSBxLnksIHEueAogICAgZm9yIHAgaW4gdToKICAgICAgICBpZiBwLnggPT0gcS54OiByZXR1cm4gRmFsc2UKICAgIHUuYXBwZW5kKHEpCiAgICByZXR1cm4gdQoKIyAgICBGaW5kIGFsbCBwYWlycyB4PjAgYW5kIHk+MCB3aGljaCBzYXRpc2Z5IHheMit5XjI9biAoeDx5KS4KIyAgICBuIGlzIHRoZSBmb3JtIG9mIGV4cG9uZW50IGV4cHJlc3Npb24uCmRlZiBzcXVhcmVfc3VtX29mX2ludGVnZXIodik6CiAgICBuID0gMAogICAgdSwgdjEsIHYyID0gW10sIFtdLCBbXQogICAgZm9yIHAgaW4gdjoKICAgICAgICBpZiBwLmJhc2UgPT0gMiBvciBwLmJhc2UgJSA0ID09IDE6CiAgICAgICAgICAgIGZvciBpIGluIHJhbmdlKHAuZXhwKTogdjEuYXBwZW5kKHAuYmFzZSkKICAgICAgICAgICAgbiArPSBwLmV4cAogICAgICAgIGVsc2U6CiAgICAgICAgICAgIGlmIHAuZXhwICUgMiAhPSAwOiByZXR1cm4gRmFsc2UKICAgICAgICAgICAgZm9yIGkgaW4gcmFuZ2UocC5leHAgLyAyKTogdjIuYXBwZW5kKHAuYmFzZSkKICAgIGlmIGxlbih2MSkgPT0gMDoKICAgICAgICBxID0gUGFpcigxLCAwKQogICAgICAgIGZvciBwIGluIHY6CiAgICAgICAgICAgIGZvciBpIGluIHJhbmdlKHAuZXhwKTogcS54ICo9IHAuYmFzZQogICAgICAgIHUuYXBwZW5kKHEpCiAgICAgICAgcmV0dXJuIGZhbHNlCiAgICB3ID0gW10KICAgIHIgPSBzcXVhcmVfc3VtX29mX3ByaW1lX2J5X3NlcnJldCh2MVswXSkKICAgIGlmIHIgPT0gTm9uZToKICAgICAgICByLnggPSByLnkgPSB2MVswXQogICAgdS5hcHBlbmQocikKICAgIGZvciBpIGluIHJhbmdlKDEsIGxlbih2MSkpOgogICAgICAgIHIgPSBzcXVhcmVfc3VtX29mX3ByaW1lX2J5X3NlcnJldCh2MVtpXSkKICAgICAgICBpZiByICE9IE5vbmU6CiAgICAgICAgICAgIGZvciBxIGluIHU6CiAgICAgICAgICAgICAgICB3ID0gZXhwYW5kKHEueCwgcS55LCByLngsIHIueSwgdykKICAgICAgICAgICAgICAgIHcgPSBleHBhbmQocS54LCBxLnksIHIueSwgci54LCB3KQogICAgICAgIHUsIHcgPSB3LCB1CiAgICAgICAgdyA9IFtdCiAgICBmb3IgaSBpbiByYW5nZSgxLCBsZW4odjIpKToKICAgICAgICBmb3IgcSBpbiB1OgogICAgICAgICAgICBxLnggKj0gdjJbaV0KICAgICAgICAgICAgcS55ICo9IHYyW2ldCiAgICByZXR1cm4gdQoKZGVmIHNvbHZlKG4pOgogICAgciA9IDAKICAgIHQgPSAxMCoqKG4vMikKICAgIHYgPSBbXQogICAgdSA9IFtdCiAgICBtID0gdCp0ICsgMQoKICAgIHAgPSBmYWN0b3IobSkKICAgIHAuc29ydCgpCiAgICBxID0gUG93KHBbMF0sIDEpCiAgICBmb3IgaSBpbiByYW5nZSgxLCBsZW4ocCkpOgogICAgICAgIGlmIHBbaV0gIT0gcFtpLTFdOgogICAgICAgICAgICB2LmFwcGVuZChxKQogICAgICAgICAgICBxID0gUG93KHBbaV0sIDEpCiAgICAgICAgZWxzZTogcS5leHAgKz0gMQogICAgdi5hcHBlbmQocSkKCiAgICB1ID0gc3F1YXJlX3N1bV9vZl9pbnRlZ2VyKHYpCgogICAgZm9yIHMgaW4gdToKICAgICAgICBpZiBzLnggJSAyICE9IDA6IHMueCwgcy55ID0gcy55LCBzLngKICAgICAgICB4ID0gdCAvIDIgKyBzLnggLyAyCiAgICAgICAgeSA9ICgxICsgcy55KSAvIDIKICAgICAgICBpZiB4ID49IHQgLyAxMCBhbmQgeCA8IHQgYW5kIHkgPCB0OgojICAgICAgICAgICAgcHJpbnQgIiAgIiArIHN0cih0ICogeCArIHkpCiAgICAgICAgICAgIHIgKz0gdCAqIHggKyB5CiAgICAgICAgeCA9IHQgLyAyIC0gcy54IC8gMgogICAgICAgIGlmIHggPj0gdCAvIDEwIGFuZCB4IDwgdCBhbmQgeSA8IHQ6CiMgICAgICAgICAgICBwcmludCAiICAiICsgc3RyKHQgKiB4ICsgeSkKICAgICAgICAgICAgciArPSB0ICogeCArIHkKICAgIHByaW50IHN0cihuKSArICc6ICcgKyBzdHIocikKCmZvciBuIGluIHJhbmdlKDIsIDM4LCAyKToKCXNvbHZlKG4pCnNvbHZlKDY4KQ==