Given a natural number A, I want to find all the pairs of natural numbers (B,C) so that B*C*(C+1) = A

后端 未结 3 1488
情书的邮戳
情书的邮戳 2021-02-06 08:45

What\'s the fastest way to do it?

My simple aproach:

for (C = 1;C

        
相关标签:
3条回答
  • 2021-02-06 09:20

    It can be done in O(cube_root(A))
    Indeed, one of your numbers B and C must be less than cube_root(A)

    0 讨论(0)
  • 2021-02-06 09:28

    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)]
    
    0 讨论(0)
  • 2021-02-06 09:43

    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.

    0 讨论(0)
提交回复
热议问题