What\'s the fastest way to do it?
My simple aproach:
for (C = 1;C
It can be done in O(cube_root(A))
Indeed, one of your numbers B
and C
must be less than cube_root(A)
This python seems to work:
from __future__ import division
from math import sqrt
def bcc1(a):
ans = []
if a % 2: return ans # for odd a
for b in range(1, a // 2 + 1):
c = max(1, int(sqrt(a / b)))
if b*c*(c+1) == a:
ans.append((b,c))
return ans
for a in range(2, 51, 2):
print('a: %2i -> (b, c): %r' % (a, bcc1(a)))
The output produced is:
a: 2 -> (b, c): [(1, 1)]
a: 4 -> (b, c): [(2, 1)]
a: 6 -> (b, c): [(1, 2), (3, 1)]
a: 8 -> (b, c): [(4, 1)]
a: 10 -> (b, c): [(5, 1)]
a: 12 -> (b, c): [(1, 3), (2, 2), (6, 1)]
a: 14 -> (b, c): [(7, 1)]
a: 16 -> (b, c): [(8, 1)]
a: 18 -> (b, c): [(3, 2), (9, 1)]
a: 20 -> (b, c): [(1, 4), (10, 1)]
a: 22 -> (b, c): [(11, 1)]
a: 24 -> (b, c): [(2, 3), (4, 2), (12, 1)]
a: 26 -> (b, c): [(13, 1)]
a: 28 -> (b, c): [(14, 1)]
a: 30 -> (b, c): [(1, 5), (5, 2), (15, 1)]
a: 32 -> (b, c): [(16, 1)]
a: 34 -> (b, c): [(17, 1)]
a: 36 -> (b, c): [(3, 3), (6, 2), (18, 1)]
a: 38 -> (b, c): [(19, 1)]
a: 40 -> (b, c): [(2, 4), (20, 1)]
a: 42 -> (b, c): [(1, 6), (7, 2), (21, 1)]
a: 44 -> (b, c): [(22, 1)]
a: 46 -> (b, c): [(23, 1)]
a: 48 -> (b, c): [(4, 3), (8, 2), (24, 1)]
a: 50 -> (b, c): [(25, 1)]
Step 1: Factor A
Step 2: Find the set S of all divisors from the prime factors of A.
Step 3: For each divisor c in S, check if c+1 divides A too. If it does then b=A/(c*(c+1)) is a solution. (This uses that c and c+1 are coprime. Thus if both c and c+1 divide A then so does c*(c+1)).
The complexity of this depends on the method that is used for factor A. E.g., if you implement for example Pollard-rho (which is relatively simple) then the complexity of the implementation is about O(A^0.25) in the worst case. And this still isn't the best possible answer. There are of course better factoring algorithm. Also if your input is a special case with lots of divisors, then factoring can be easy and the number of divisors is the limiting problem.
The advantage of this method is of course that you'll spend your time on a generally useful function (i.e factorization), which will simplify solving other similar problems. My own implementation of Pollard-rho in Python needs a total of 0.03 s for the 20 examples with 15 digits posted by 6502, which is already at least a speedup of a factor 1000. More sophisticated implementations should lead to much larger improvements.
For comparison, a quick and dirty Python implementation of the O(A^(1/3)) method proposed by Egor Skriptunoff needs 0.7s for the same list. This is of course a good result for a method that is easy to implement.