# identifying squares, revisited
def isqrt(n):
if n < 1: return 0
u, s = n, n+1
while u < s:
s = u
t = s + n // s
u = t // 2
return s
def isSquare(n): # naive
s = isqrt(n); return s*s == n
def isSquare(n): # fenderbender
m = n & 127
if ((m*0x8bc40d7d) & (m*0xa1e2f5d1) & 0x14020a): return False
largeMod = n % (63*25*11*17*19*23*31)
m = largeMod % 63
if ((m*0x3d491df7) & (m*0xc824a9f9) & 0x10f14008): return False
m = largeMod % 25
if ((m*0x1929fc1b) & (m*0x4c9ea3b2) & 0x51001005): return False
m = 0xd10d829a * (largeMod % 31)
if (m & (m+0x672a5354) & 0x21025115): return False
m = largeMod % 23
if ((m*0x7bd28629) & (m*0xe7180889) & 0xf8300): return False
m = largeMod % 19
if ((m*0x1b8bead3) & (m*0x4d75a124) & 0x4280082b): return False
m = largeMod % 17
if ((m*0x6736f323) & (m*0x9b1d499) & 0xc0000300): return False
m = largeMod % 11
if ((m*0xabf1a3a7) & (m*0x2612bf93) & 0x45854000): return False
s = isqrt(n); return s*s == n
def isSquare(n):
# def q(n):
# from sets import Set
# s, sum = Set(), 0
# for x in xrange(0,n):
# t = pow(x,2,n)
# if t not in s:
# s.add(t)
# sum += pow(2,t)
# return len(s), sum
# q(64) = 12, 144680414395695635
# q(63) = 16, 288872697407275667
# q(52) = 14, 845593731871251
# q(55) = 18, 615814660213299
# q(57) = 20, 54655143861879507
# q(51) = 18, 576239692522003
# about 99.77% of non-squares are caught by the
# filters prior to computation of the square root
if 144680414395695635 >> (n%64) & 1 == 0: return False
if 288872697407275667 >> (n%63) & 1 == 0: return False
if 845593731871251 >> (n%52) & 1 == 0: return False
if 615814660213299 >> (n%55) & 1 == 0: return False
if 54655143861879507 >> (n%57) & 1 == 0: return False
if 576239692522003 >> (n%51) & 1 == 0: return False
s = isqrt(n); return s*s == n
print isSquare(36)
print isSquare(27)
print isSquare(123412341234*123412341234)
IyBpZGVudGlmeWluZyBzcXVhcmVzLCByZXZpc2l0ZWQKCmRlZiBpc3FydChuKToKICBpZiBuIDwgMTogcmV0dXJuIDAKICB1LCBzID0gbiwgbisxCiAgd2hpbGUgdSA8IHM6CiAgICBzID0gdQogICAgdCA9IHMgKyBuIC8vIHMKICAgIHUgPSB0IC8vIDIKICByZXR1cm4gcwoKZGVmIGlzU3F1YXJlKG4pOiAjIG5haXZlCiAgcyA9IGlzcXJ0KG4pOyByZXR1cm4gcypzID09IG4KCmRlZiBpc1NxdWFyZShuKTogIyBmZW5kZXJiZW5kZXIKICBtID0gbiAmIDEyNwogIGlmICgobSoweDhiYzQwZDdkKSAmIChtKjB4YTFlMmY1ZDEpICYgMHgxNDAyMGEpOiByZXR1cm4gRmFsc2UKICBsYXJnZU1vZCA9IG4gJSAoNjMqMjUqMTEqMTcqMTkqMjMqMzEpCiAgbSA9IGxhcmdlTW9kICUgNjMKICBpZiAoKG0qMHgzZDQ5MWRmNykgJiAobSoweGM4MjRhOWY5KSAmIDB4MTBmMTQwMDgpOiByZXR1cm4gRmFsc2UKICBtID0gbGFyZ2VNb2QgJSAyNQogIGlmICgobSoweDE5MjlmYzFiKSAmIChtKjB4NGM5ZWEzYjIpICYgMHg1MTAwMTAwNSk6IHJldHVybiBGYWxzZQogIG0gPSAweGQxMGQ4MjlhICogKGxhcmdlTW9kICUgMzEpIAogIGlmIChtICYgKG0rMHg2NzJhNTM1NCkgJiAweDIxMDI1MTE1KTogcmV0dXJuIEZhbHNlCiAgbSA9IGxhcmdlTW9kICUgMjMKICBpZiAoKG0qMHg3YmQyODYyOSkgJiAobSoweGU3MTgwODg5KSAmIDB4ZjgzMDApOiByZXR1cm4gRmFsc2UKICBtID0gbGFyZ2VNb2QgJSAxOQogIGlmICgobSoweDFiOGJlYWQzKSAmIChtKjB4NGQ3NWExMjQpICYgMHg0MjgwMDgyYik6IHJldHVybiBGYWxzZQogIG0gPSBsYXJnZU1vZCAlIDE3IAogIGlmICgobSoweDY3MzZmMzIzKSAmIChtKjB4OWIxZDQ5OSkgJiAweGMwMDAwMzAwKTogcmV0dXJuIEZhbHNlCiAgbSA9IGxhcmdlTW9kICUgMTEgCiAgaWYgKChtKjB4YWJmMWEzYTcpICYgKG0qMHgyNjEyYmY5MykgJiAweDQ1ODU0MDAwKTogcmV0dXJuIEZhbHNlCiAgcyA9IGlzcXJ0KG4pOyByZXR1cm4gcypzID09IG4KCmRlZiBpc1NxdWFyZShuKToKICAjIGRlZiBxKG4pOgogICMgICBmcm9tIHNldHMgaW1wb3J0IFNldAogICMgICBzLCBzdW0gPSBTZXQoKSwgMAogICMgICBmb3IgeCBpbiB4cmFuZ2UoMCxuKToKICAjICAgICB0ID0gcG93KHgsMixuKQogICMgICAgIGlmIHQgbm90IGluIHM6CiAgIyAgICAgICBzLmFkZCh0KQogICMgICAgICAgc3VtICs9IHBvdygyLHQpCiAgIyAgIHJldHVybiBsZW4ocyksIHN1bQogICMgcSg2NCkgPSAxMiwgMTQ0NjgwNDE0Mzk1Njk1NjM1CiAgIyBxKDYzKSA9IDE2LCAyODg4NzI2OTc0MDcyNzU2NjcKICAjIHEoNTIpID0gMTQsICAgIDg0NTU5MzczMTg3MTI1MQogICMgcSg1NSkgPSAxOCwgICAgNjE1ODE0NjYwMjEzMjk5CiAgIyBxKDU3KSA9IDIwLCAgNTQ2NTUxNDM4NjE4Nzk1MDcKICAjIHEoNTEpID0gMTgsICAgIDU3NjIzOTY5MjUyMjAwMwogICMgYWJvdXQgOTkuNzclIG9mIG5vbi1zcXVhcmVzIGFyZSBjYXVnaHQgYnkgdGhlCiAgIyBmaWx0ZXJzIHByaW9yIHRvIGNvbXB1dGF0aW9uIG9mIHRoZSBzcXVhcmUgcm9vdAogIGlmIDE0NDY4MDQxNDM5NTY5NTYzNSA+PiAobiU2NCkgJiAxID09IDA6IHJldHVybiBGYWxzZQogIGlmIDI4ODg3MjY5NzQwNzI3NTY2NyA+PiAobiU2MykgJiAxID09IDA6IHJldHVybiBGYWxzZQogIGlmICAgIDg0NTU5MzczMTg3MTI1MSA+PiAobiU1MikgJiAxID09IDA6IHJldHVybiBGYWxzZQogIGlmICAgIDYxNTgxNDY2MDIxMzI5OSA+PiAobiU1NSkgJiAxID09IDA6IHJldHVybiBGYWxzZQogIGlmICA1NDY1NTE0Mzg2MTg3OTUwNyA+PiAobiU1NykgJiAxID09IDA6IHJldHVybiBGYWxzZQogIGlmICAgIDU3NjIzOTY5MjUyMjAwMyA+PiAobiU1MSkgJiAxID09IDA6IHJldHVybiBGYWxzZQogIHMgPSBpc3FydChuKTsgcmV0dXJuIHMqcyA9PSBuCgpwcmludCBpc1NxdWFyZSgzNikKcHJpbnQgaXNTcXVhcmUoMjcpCnByaW50IGlzU3F1YXJlKDEyMzQxMjM0MTIzNCoxMjM0MTIzNDEyMzQp