A natural number, N, that can be written as the sum and product of a given set of at least two natural numbers, {a1, a2, ... , ak} is called a product-sum number: N = a1 + a2 + ... + ak = a1 × a2 × ... × ak.

For example, 6 = 1 + 2 + 3 = 1 × 2 × 3.

For a given set of size, k, we shall call the smallest N with this property a minimal product-sum number. The minimal product-sum numbers for sets of size, k = 2, 3, 4, 5, and 6 are as follows.

k=2: 4 = 2 × 2 = 2 + 2

k=3: 6 = 1 × 2 × 3 = 1 + 2 + 3

k=4: 8 = 1 × 1 × 2 × 4 = 1 + 1 + 2 + 4

k=5: 8 = 1 × 1 × 2 × 2 × 2 = 1 + 1 + 2 + 2 + 2

k=6: 12 = 1 × 1 × 1 × 1 × 2 × 6 = 1 + 1 + 1 + 1 + 2 + 6

Hence for 2≤k≤6, the sum of all the minimal product-sum numbers is 4+6+8+12 = 30; note that 8 is only counted once in the sum.

In fact, as the complete set of minimal product-sum numbers for 2≤k≤12 is {4, 6, 8, 12, 15, 16}, the sum is 61.

What is the sum of all the minimal product-sum numbers for 2≤k≤12000?


In [1]:
import itertools
import numpy as np
def prime_factors(n): # from eratosthenes
    factors = []
    d = 2
    while n > 1:
        while n % d == 0:
            factors.append(d)
            n /= d
        
        d = d + 1
        if d * d > n:
            if n > 1:
                factors.append(n)
            break
            
    return factors

def powerset(iterable): # from itertools
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)
    return itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s)+1))

def proper_divisors(n):
    pf = prime_factors(n)
    factors = []
    for p in set(powerset(pf)):
        factors.append(int(np.prod(np.array(p))))
        
    return sorted(factors)[:-1]
    
print proper_divisors(n=220)


[1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110]

In [141]:
import math
import time
import calendar

def factorizations(n):
    divisors = proper_divisors(n)
    
    facts = set()
    for i,d in enumerate(divisors):
        if d == 1:
            continue
            
        b = n/d
        facts.add(tuple(sorted([b,d])))
        for f in factorizations(b):
            f = list(f)
            f.append(d)
            facts.add(tuple(sorted(f)))
    return facts

def is_prod_sum(n, k):
    for f in factorizations(n):
        if len(f) == k and sum(f) == n:
            #print f
            return True
        elif len(f) < k and sum(f) == n - (k - len(f)):
            #print f, '+ 1 *', k - len(f)
            return True
    
    return False

time_start = calendar.timegm(time.gmtime())

min_set = set()
max_k = 12000
for k in range(2,max_k):
    for n in range(k,int(max_k*1.5)):
        if is_prod_sum(n, k):
            #print "k =",k,"n =",n
            min_set.add(n)
            break
print sum(min_set), len(min_set)

time_stop = calendar.timegm(time.gmtime())
print time_stop - time_start, 'seconds'


test
test
123656 232 set([512, 768, 1026, 4, 6, 8, 855, 12, 525, 15, 16, 600, 18, 20, 24, 1050, 27, 28, 30, 32, 832, 546, 36, 550, 40, 42, 45, 1071, 48, 54, 567, 56, 570, 60, 63, 64, 864, 1092, 70, 72, 588, 80, 81, 594, 595, 84, 88, 612, 90, 1116, 702, 96, 528, 1122, 100, 1125, 616, 105, 108, 110, 112, 625, 1140, 117, 630, 120, 125, 126, 128, 704, 644, 135, 648, 140, 144, 792, 1170, 660, 1134, 150, 152, 156, 160, 624, 162, 539, 960, 168, 540, 684, 686, 175, 176, 1224, 180, 693, 184, 700, 189, 190, 1215, 192, 800, 1024, 200, 714, 1200, 208, 1144, 210, 1216, 216, 729, 224, 720, 891, 228, 234, 1184, 748, 750, 240, 1064, 243, 756, 248, 980, 250, 252, 256, 640, 260, 264, 780, 270, 1120, 272, 280, 798, 288, 560, 896, 1152, 1040, 297, 810, 300, 816, 306, 308, 312, 825, 315, 828, 320, 324, 1078, 840, 1164, 330, 336, 1080, 342, 343, 858, 348, 350, 351, 352, 912, 360, 572, 875, 880, 882, 884, 375, 888, 378, 575, 380, 384, 576, 900, 392, 396, 910, 400, 920, 405, 918, 408, 924, 416, 931, 420, 935, 936, 425, 696, 432, 945, 952, 950, 1232, 440, 441, 448, 672, 450, 1100, 972, 462, 675, 468, 1188, 476, 990, 480, 1104, 484, 486, 1056, 1000, 495, 1008, 680, 500, 504, 1176, 1020, 784])
30 seconds

In [119]:
max(min_set) # 12200. 7587457. 1409


Out[119]:
12200

In [ ]: