Project Euler #169: Exploring the number of different ways a number can be expressed as a sum of powers of 2.

  • + 0 comments

    PyPy3 solution:

    from math import log
    
    d = {}
    
    def num_ways(N):
        if N in d:
            return d[N]
        if N <= 1:
            return 1
        if N & 1:
            return num_ways(N >> 1)
        d[N] = num_ways(N >> 1) + num_ways((N >> 1) - 1)
        return d[N]
            
    n = int(input())
    
    
    print(num_ways(n))
    

    The recurrence comes from generating functionology. E.g. suppose N = 10. int(log(N, 2)) = 3. Thus, the generating function of this is (1 + x + x^2)(1 + x^2 + x^4)(1 + x^4 + x^8). In general, when int(log(N, 2)) = k, we have: Pk = (1 + x + x^2)...(1 + x^(2^k) + x^(2^(k + 1)) ).

    The solution is the coefficient in front of x^N Now, to obtain the reccurence, consider the following two cases: 2N + 1 and 2N. coeff(Pk, 2N + 1) = coeff(x * P_{k - 1}(x^2), 2N + 1) = coeff(P_{k - 1}, N) coeff(Pk, 2N) = coeff((1 + x^2)P_{k - 1}(x^2), 2N) = coeff(P_{k - 1}, N - 1) + coeff(P_{k - 1}, N)

    It follows that f(2N + 1) = f(N) and f(2N) = f(N - 1) + f(N).