I have to find a solution to the equation x2 + y2 = m where m can be any natural number and x,y are integers. This can be done in O(m1/2) by using brute force easily. Is there a way I can do this in constant time?
-
5`x = sqrt(m), y = 0`. Or, if `x` and `y` are supposed to be integral, you probably should have said so :-) – paxdiablo Jan 17 '17 at 08:15
-
what is known and unknown? what are x,y? integers > 0 , R , C? If `m` is known and x,y are unknonw then for limited `m` you can use LUT which is `O(1)` – Spektre Jan 17 '17 at 08:15
-
@Sujay_K and what is unknown? – Spektre Jan 17 '17 at 08:19
-
A solution or all solutions? – Simon Jan 17 '17 at 08:20
-
1This question is offtopic here and belongs to a dedicated Math SE site, for instance here http://mathoverflow.net/ – walther Jan 17 '17 at 08:20
-
m is known and x,y are to be found. @Spektre – Sujay_K Jan 17 '17 at 08:22
-
@paxdiablo You meant integer perhaps? I got confused for two minutes thinking about calculus solutions. – luk32 Jan 17 '17 at 08:24
-
A solution. @Simon – Sujay_K Jan 17 '17 at 08:24
-
@luk32, integral as an adjective means (among other definitions) `of or denoted by an integer`, the *noun* integral would indeed be calculus but then I would have written "*an* integral". Now deactivating "PITA pedant" mode :-) – paxdiablo Jan 17 '17 at 08:41
-
2@walther mathoverflow is research-level mathematics. This asker wants [math.se] – AakashM Jan 17 '17 at 09:23
-
1I'm voting to close this question as off-topic because it is more suitable for [math.se] – Ken White Jan 17 '17 at 23:31
1 Answers
I'm not sure you can do it any better than O(sqrt(m))
for an arbitrary m
but that's pretty damn good , much better than linear time :-)
The approach is to start x
and y
at opposite ends of the solution space and either increment the low end or decrement the high end, depending on whether the result is too low or too high (obviously if the result is perfect, return the values):
def solveForM(m):
set lo to 0
set hi to sqrt(m), rounded up.
while lo < hi:
testVal = lo * lo + hi * hi
if testVal == m:
return (lo, hi)
if testVal > m:
hi = hi - 1
else lo = lo + 1
return "No solution"
If m
can be limited somehow, you could achieve O(1)
by use of a lookup table (many optimisations come down to trading space for time), such as:
0 -> 0, 0
1 -> 0, 1
2 -> 1, 1
No solution for 3
4 -> 0, 2
5 -> 1, 2
No solution for 6, 7
8 -> 2, 2
9 -> 0, 3
10 -> 1, 3
No solution for 11, 12
13 -> 2, 3
... and so on.
A table like this can be generated with a small program along the lines of (Python 3):
for hi in range(1001):
for lo in range(1001):
m = lo * lo + hi * hi
print("%5d -> %d, %d"%(m, lo, hi))
You have to sort (and possibly remove duplicates) afterwards to create a fast look-up table but the performance is okay with the generation of an unsorted list taking fifteen seconds for all m
up to two million.
In any case, this is only run once, after which you would place the table into code where the time expense is incurred at compile time.

- 854,327
- 234
- 1,573
- 1,953
-
-
1You can definitely do better: for prime `m`, there's an algorithm based on Fermat's descent method that will give a solution in polynomial time in `log(m)`. And for non-prime `m`, it's possible to build all solutions from the solutions for prime `m`. So for large composite `m`, the bottleneck essentially comes down to the time to factorise `m`. For a Python solution for prime inputs, see http://math.stackexchange.com/a/5883/117283 – Mark Dickinson Jan 17 '17 at 08:41
-
@MBo `set hi to sqrt(m), rounded up` is possibly the problem I am using `hi=sqrt(m)+1` which is fine – Spektre Jan 17 '17 at 12:33
-
@MBo, assuming you meant in the lookup table (where that exact text is), it's not so much a rounding error as it is faulty manual calculations on my part. I probably should have created the table with some code rather than relying on faulty wetware :-) Fixed now. – paxdiablo Jan 17 '17 at 23:32