The problem in PE 108 is to find such an n for a equation \( \frac{1}{x} + \frac{1}{y} = \frac{1}{n} \), where x, y, n are all integers, and where number of disctinct solutions exceeds 1000.
It was easy, I solved it using Wolfram Mathematica:
countSolutions[n_] :=
Length[Solve[1/x + 1/y == 1/n && x > 0 && y > 0 && x >= y, {x, y},
Integers]]
Do[cnt = countSolutions[n];
If[cnt > 1000, Print[{n, cnt}]; Abort[]], {n, 1, 10^10}]
Slow (several hours), but doable.
PE 110 problem harder -- the bar is raised up to \( 4 \cdot 10^6 \) solutions. No bruteforce is possible.
In the thread on PE about problem 108, I've found a mention about OEIS A018892. I hooked on this clue and tried not to read other solutions and hints. OK, what is this?
A018892 Number of ways to write 1/n as a sum of exactly 2 unit fractions
a(n) = (tau(n^2)+1)/2. Number of elements in the set {(x,y): x|n, y|n, x<=y, gcd(x,y)=1}
In Wolfram Mathematica, it can be expressed as:
A018892[n_] := (Length[Divisors[n^2]] + 1)/2
The problem is now different. Find such a (minimal) number for which A018892 function will exceed \( 4 \cdot 10^6 \). In other words, find a (minimal) number for which Divisors[] function will exceed \( 2 \cdot 4 \cdot 10^6 - 1 \).
Let's ask ourselves, how to find number of divisors? Oh, it's easy, just factorize that number. For example: 12348. Run msieve with it. It will say:
Wed Jul 17 00:56:20 2024 factoring 12348 (5 digits) Wed Jul 17 00:56:20 2024 p1 factor: 2 Wed Jul 17 00:56:20 2024 p1 factor: 2 Wed Jul 17 00:56:20 2024 p1 factor: 3 Wed Jul 17 00:56:20 2024 p1 factor: 3 Wed Jul 17 00:56:20 2024 p1 factor: 7 Wed Jul 17 00:56:20 2024 p1 factor: 7 Wed Jul 17 00:56:20 2024 p1 factor: 7
Indeed, \( 2\cdot 2\cdot 3\cdot 3\cdot 7\cdot 7\cdot 7==12348 \). Another way of representing it is: \( 2^ 2\cdot 3^2 \cdot 7^3 \).
This expression can be viewed as: \( p1^{c1} \cdot p2^{c2} \cdot ...\), where p1, p2 - prime numbers and c1, c2 -- coefficients or powers or exponents.
Number of divisors is: \( (c1+1)(c2+1)(c3+1)... \) For our number, coefficients are 2, 2 and 3. \( (2+1)(2+1)(3+1)=36 \).
Yes, 36 divisors, let's check in Wolfram Mathematica:
In[]:= Length@Divisors[12348] Out[]= 36
Now another question, how can you find a number that has 4099948 solutions? Or \( 2 \cdot 4099948-1=8199895 \) divisors? Ah, it's easy. Factor this number:
In[]:= FactorInteger[2*4099948-1]
Out[]= {{5, 1}, {11, 1}, {29, 1}, {53, 1}, {97, 1}}
There are 5 primes: 5, 11, 29, 53 and 97. But in fact, these are only coefficients to another expression.
We only have to find p1, p2, p3, p4 and p5 for the expression: \( p1^{5-1} \cdot p2^{11-1} \cdot p3^{29-1} \cdot p4^{53-1} \cdot p5^{97-1} \). Let's plug first 5 primes:
In[]:= p1=2; p2=3; p3=5; p4=7; p5=11; In[]:= x=p1^(5-1) * p2^(11-1) * p3^(29-1) * p4^(53-1) * p5^(97-1) Out[]= 291936574071356139797183542300802080273263700534750232097183894934260994188740440655397\ 62795433862023628730959481433237126302432907576845964140240483880043029785156250000 In[]:= Length@Divisors[x] Out[]= 8199895
In other words, number of solutions of equation \( \frac{1}{x} + \frac{1}{y} = \frac{1}{n} \) is 4099948, where n is:
In[]:= Sqrt[x] Out[]= 5403115527835363060896154958947115524913225008014850942090010084438627775073242187500
So far so good. But this number is too big.
Now the problem is to find such a group of 5 (distinct) primes for which that number will be minimized.
Simplest idea -- just sort that list, let first (smallest) prime have biggest coefficient and last (biggest) prime have smallest coefficient.
#!/usr/bin/python3
import math
# https://math.stackexchange.com/questions/1039519/finding-prime-factors-by-taking-the-square-root
# DIY factoring functions, but for small numbers it is OK
def factor_helper(n):
for i in range(2, int(math.ceil(math.sqrt(n)))+1):
if n % i == 0:
return i
# this is prime
return n
def factor(n):
rt=[]
while True:
p=factor_helper(n)
if p==1:
break
rt.append (p)
n=n//p
return rt
first_primes=[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
smallest_result=-1
smallest_divisors=-1
smallest_solutions=-1
def try_(solutions_we_want, divisors_we_want):
global smallest_result
global smallest_divisors
global smallest_solutions
factors=factor(divisors_we_want)
if max(factors)>100:
# skip it, because we need small results anyway
return
factors=sorted(factors, reverse=True)
rt=1
for p, f in zip(first_primes, factors):
rt*=p**(f-1)
try:
result=int(math.sqrt(rt))
except OverflowError:
# skip it, because we need small results anyway
return
print (divisors_we_want, result)
if (smallest_result==-1) or (result<smallest_result):
smallest_result=result
smallest_divisors=divisors_we_want
smallest_solutions=solutions_we_want
#for solutions_we_want in range(1000, 2000): # for PE 108
for solutions_we_want in range(4*10**6, 4*10**6+100000): # for PE 110
divisors_we_want=(solutions_we_want*2)-1;
try_ (solutions_we_want, divisors_we_want)
print (f"{smallest_result=}")
print (f"{smallest_solutions=}")
print (f"{smallest_divisors=}")
And that worked. For PE 108:
smallest_result=180180 smallest_solutions=1013 smallest_divisors=2025
For PE 110:
smallest_result=9350130049860600 smallest_solutions=4018613 smallest_divisors=8037225
And both 180180 and 9350130049860600 numbers are happens to be there:
A126098 Where records occur in A018892.
As if Project Euler author took idea right from here. Maybe it was so. But the code at OEIS is simpler than mine.

Yes, I know about these lousy Disqus ads. Please use adblocker. I would consider to subscribe to 'pro' version of Disqus if the signal/noise ratio in comments would be good enough.