def recurse(number,primeindex,divisors,lastexp):
    global primes, smallest, solutions
    if divisors > 2*solutions:
        print(':',number,divisors,lib.prime_factorization(number),
              lib.divisors2(number))
        smallest = min(smallest,number)
        return # multiplying more would only make the number larger
    curexp = 2
    number *= primes[primeindex]**2
    divisors *= 3 # repeatedly multiply squares of current prime
    while number < smallest and curexp <= lastexp:
        recurse(number,primeindex+1,divisors,curexp)
        number *= primes[primeindex]**2
        curexp += 2
        divisors = divisors * (curexp+1) // (curexp-1)
import libtkoz as lib

divisors = 500

# faster solution using a few properties
# first, compute the number of divisors by factoring
# if n = p^a * q^b * ..., (p q prime, a b exponents), divisors = (a+1)*(b+1)*...
# triangle numbers are n(n+1)/2 so the property of coprime can be used
# if n=pq, p q coprime, then divisors(n) = divisors(p) * divisors(q)
# if n odd then (n+1)/2 and n are coprime, n even --> n/2 and n+1 coprime
# this can be shown trivially with eulers gcd algorithm
# the sequence can be computing like below:
# 1*(2/2), (2/2)*3, 3*(4/2), (4/2)*5, 5*(6/2), (6/2)*7, 7*(8/2), (8/2)*9, ...
divs_odd = 1
divs_even = 1
i = 2
while True:  # loop with i being later number, calculate number as i(i-1)/2
    if i % 2 == 0:  # even, count factors of i/2
        divs_even = lib.divisors2(i // 2)
    else:  # odd, count factors of i
        divs_odd = lib.divisors2(i)
    if divs_even * divs_odd > divisors:
        print(': divisors =', divs_even * divs_odd)
        print(i * (i - 1) // 2)
        break
    i += 1
# n(x+y)=xy --> n(2n+x0+y0)=n^2+nx0+ny0+x0y0 --> n^2=x0y0
# we need the smallest perfect square with enough distinct ways to factor it
# into x0*y0 such that x0<=y0. every factor x0<=n corresponds to a y0=n/x0 so
# n^2 must have 1000 divisors <= n, or 1999 overall (exclude counting n twice)
# any perfect square will have an odd number of divisors (counting divisors with
# the product of 1+ prime exponents) so we need a n^2 with >2*solutions divisors

primes = [] # find enough primes so that 3^(prime count)>2*solutions
n = 2
while 3**len(primes) <= 2*solutions:
    if lib.prime(n): primes.append(n)
    n += 1
print(': generated primes',primes)
smallest = reduce(lambda x,y:x*y, (p*p for p in primes))
print(': initial product of the squares is',smallest)
print(':',smallest,lib.divisors2(smallest),lib.prime_factorization(smallest))

# recurse on the prime list to find a smaller number with over 2000 divisors
# order exponents in decreasing order, 2^a*3^b has (a+1)(b+1) divisors so order
# a >= b (put the greater exponent on the smaller number
def recurse(number,primeindex,divisors,lastexp):
    global primes, smallest, solutions
    if divisors > 2*solutions:
        print(':',number,divisors,lib.prime_factorization(number),
              lib.divisors2(number))
        smallest = min(smallest,number)
        return # multiplying more would only make the number larger
    curexp = 2
    number *= primes[primeindex]**2
    divisors *= 3 # repeatedly multiply squares of current prime
    while number < smallest and curexp <= lastexp:
# n(x+y)=xy --> n(2n+x0+y0)=n^2+nx0+ny0+x0y0 --> n^2=x0y0
# we need the smallest perfect square with enough distinct ways to factor it
# into x0*y0 such that x0<=y0. every factor x0<=n corresponds to a y0=n/x0 so
# n^2 must have 1000 divisors <= n, or 1999 overall (exclude counting n twice)
# any perfect square will have an odd number of divisors (counting divisors with
# the product of 1+ prime exponents) so we need a n^2 with >2*solutions divisors

primes = []  # find enough primes so that 3^(prime count)>2*solutions
n = 2
while 3**len(primes) <= 2 * solutions:
    if lib.prime(n): primes.append(n)
    n += 1
print(': generated primes', primes)
smallest = reduce(lambda x, y: x * y, (p * p for p in primes))
print(': initial product of the squares is', smallest)
print(':', smallest, lib.divisors2(smallest),
      lib.prime_factorization(smallest))


# recurse on the prime list to find a smaller number with over 2000 divisors
# order exponents in decreasing order, 2^a*3^b has (a+1)(b+1) divisors so order
# a >= b (put the greater exponent on the smaller number
def recurse(number, primeindex, divisors, lastexp):
    global primes, smallest, solutions
    if divisors > 2 * solutions:
        print(':', number, divisors, lib.prime_factorization(number),
              lib.divisors2(number))
        smallest = min(smallest, number)
        return  # multiplying more would only make the number larger
    curexp = 2
    number *= primes[primeindex]**2