# sum of squares of divisors is a square
def isqrt(n): # newton
x = n; y = (x + 1) // 2
while y < x:
x=y; y=(x+n//x)//2
return x
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 sum
# q(32) => 33751571
# q(27) => 38348435
# q(25) => 19483219
# q(19) => 199411
# q(17) => 107287
# q(13) => 5659
# q(11) => 571
# q(7) => 23
# 99.82% of non-squares
# caught by filters before
# square root calculation
if 33751571>>(n%32)&1==0 or \
38348435>>(n%27)&1==0 or \
19483219>>(n%25)&1==0 or \
199411>>(n%19)&1==0 or \
107287>>(n%17)&1==0 or \
5659>>(n%13)&1==0 or \
571>>(n%11)&1==0 or \
23>>(n% 7)&1==0:
return False
s = isqrt(n)
if s * s == n: return s
return False
def factors(n): # 2,3,5-wheel
wheel = [1,2,2,4,2,4,2,4,6,2,6]
w, f, fs = 0, 2, []
while f * f <= n:
while n % f == 0:
fs.append(f); n /= f
f, w = f + wheel[w], w + 1
if w == 11: w = 3
if n == 1: return fs
else: return fs + [n]
def sigma(k, n):
# sum of k'th powers of divisors of n
# set k = 0 to get count of divisors
def add(s, p, m):
if k == 0: return s*(m+1)
s *= (p**(k*(m+1))-1)
return s / (p**k-1)
fs = factors(n)
p,m,s = fs.pop(0),1,1
while len(fs) > 0:
f = fs.pop(0)
if f <> p:
s,p,m = add(s,p,m),f,1
else: m += 1
return add(s, p, m)
def task(m,n):
result = []
for x in xrange(m,n):
if x == 1:
result.append([1,1])
else:
s = sigma(2,x)
if isSquare(s):
result.append([x,s])
return result
print task(1,250)
IyBzdW0gb2Ygc3F1YXJlcyBvZiBkaXZpc29ycyBpcyBhIHNxdWFyZQoKZGVmIGlzcXJ0KG4pOiAjIG5ld3RvbgogICAgeCA9IG47IHkgPSAoeCArIDEpIC8vIDIKICAgIHdoaWxlIHkgPCB4OgogICAgICAgIHg9eTsgeT0oeCtuLy94KS8vMgogICAgcmV0dXJuIHgKCmRlZiBpc1NxdWFyZShuKToKICAjIGRlZiBxKG4pOgogICMgZnJvbSBzZXRzIGltcG9ydCBTZXQKICAjIHMsIHN1bSA9IFNldCgpLCAwCiAgIyBmb3IgeCBpbiB4cmFuZ2UoMCxuKToKICAjICAgdCA9IHBvdyh4LDIsbikKICAjICAgaWYgdCBub3QgaW4gczoKICAjICAgICBzLmFkZCh0KQogICMgICAgIHN1bSArPSBwb3coMix0KQogICMgcmV0dXJuIHN1bQogICMgcSgzMikgPT4gMzM3NTE1NzEKICAjIHEoMjcpID0+IDM4MzQ4NDM1CiAgIyBxKDI1KSA9PiAxOTQ4MzIxOQogICMgcSgxOSkgPT4gICAxOTk0MTEKICAjIHEoMTcpID0+ICAgMTA3Mjg3CiAgIyBxKDEzKSA9PiAgICAgNTY1OQogICMgcSgxMSkgPT4gICAgICA1NzEKICAjIHEoNykgID0+ICAgICAgIDIzCiAgIyA5OS44MiUgb2Ygbm9uLXNxdWFyZXMKICAjIGNhdWdodCBieSBmaWx0ZXJzIGJlZm9yZQogICMgc3F1YXJlIHJvb3QgY2FsY3VsYXRpb24KICBpZiAzMzc1MTU3MT4+KG4lMzIpJjE9PTAgb3IgXAogICAgIDM4MzQ4NDM1Pj4obiUyNykmMT09MCBvciBcCiAgICAgMTk0ODMyMTk+PihuJTI1KSYxPT0wIG9yIFwKICAgICAgIDE5OTQxMT4+KG4lMTkpJjE9PTAgb3IgXAogICAgICAgMTA3Mjg3Pj4obiUxNykmMT09MCBvciBcCiAgICAgICAgIDU2NTk+PihuJTEzKSYxPT0wIG9yIFwKICAgICAgICAgIDU3MT4+KG4lMTEpJjE9PTAgb3IgXAogICAgICAgICAgIDIzPj4obiUgNykmMT09MDoKICAgIHJldHVybiBGYWxzZQogIHMgPSBpc3FydChuKQogIGlmIHMgKiBzID09IG46IHJldHVybiBzCiAgcmV0dXJuIEZhbHNlCgpkZWYgZmFjdG9ycyhuKTogIyAyLDMsNS13aGVlbAogIHdoZWVsID0gWzEsMiwyLDQsMiw0LDIsNCw2LDIsNl0KICB3LCBmLCBmcyA9IDAsIDIsIFtdCiAgd2hpbGUgZiAqIGYgPD0gbjoKICAgIHdoaWxlIG4gJSBmID09IDA6CiAgICAgIGZzLmFwcGVuZChmKTsgbiAvPSBmCiAgICBmLCB3ID0gZiArIHdoZWVsW3ddLCB3ICsgMQogICAgaWYgdyA9PSAxMTogdyA9IDMKICBpZiBuID09IDE6IHJldHVybiBmcwogIGVsc2U6IHJldHVybiBmcyArIFtuXQoKZGVmIHNpZ21hKGssIG4pOgogICMgc3VtIG9mIGsndGggcG93ZXJzIG9mIGRpdmlzb3JzIG9mIG4KICAjIHNldCBrID0gMCB0byBnZXQgY291bnQgb2YgZGl2aXNvcnMKICBkZWYgYWRkKHMsIHAsIG0pOgogICAgaWYgayA9PSAwOiByZXR1cm4gcyoobSsxKQogICAgcyAqPSAocCoqKGsqKG0rMSkpLTEpCiAgICByZXR1cm4gcyAvIChwKiprLTEpCiAgZnMgPSBmYWN0b3JzKG4pCiAgcCxtLHMgPSBmcy5wb3AoMCksMSwxCiAgd2hpbGUgbGVuKGZzKSA+IDA6CiAgICBmID0gZnMucG9wKDApCiAgICBpZiBmIDw+IHA6CiAgICAgIHMscCxtID0gYWRkKHMscCxtKSxmLDEKICAgIGVsc2U6IG0gKz0gMQogIHJldHVybiBhZGQocywgcCwgbSkKCmRlZiB0YXNrKG0sbik6CiAgcmVzdWx0ID0gW10KICBmb3IgeCBpbiB4cmFuZ2UobSxuKToKICAgIGlmIHggPT0gMToKICAgICAgcmVzdWx0LmFwcGVuZChbMSwxXSkKICAgIGVsc2U6CiAgICAgIHMgPSBzaWdtYSgyLHgpCiAgICAgIGlmIGlzU3F1YXJlKHMpOgogICAgICAgIHJlc3VsdC5hcHBlbmQoW3gsc10pCiAgcmV0dXJuIHJlc3VsdAoKcHJpbnQgdGFzaygxLDI1MCk=