Project Euler Problem 88 Solution

Project Euler Problem 88 Solution

Product-sum Numbers

by {BetaProjects} | Project Euler & HackerRank
Difficulty: Easy

Project Euler Problem 88 Statement

A natural number, $N$, that can be written as the sum and product of a given set of at least two natural numbers, $\{a_1, a_2, \dots, a_k\}$ is called a product-sum number: $N = a_1 + a_2 + \cdots + a_k = a_1 \times a_2 \times \cdots \times a_k$.

For example, $6 = 1 + 2 + 3 = 1 \times 2 \times 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.

Hence for $2 \le k \le 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 \le k \le 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 \le k \le 12000$?

Solution

Product-Sum Number

A natural number, \( N \), is called a product-sum number for a given \( k \) if it can be written as both the sum and the product of the same set of \( k \) positive integers. Formally:

\[ N = a_1 + a_2 + \dots + a_k = a_1 \times a_2 \times \dots \times a_k \]

For example, \( 6 = 1 + 2 + 3 = 1 \times 2 \times 3 \), so 6 is a product-sum number for \( k = 3 \).

Goal

For each \( k \) from 2 up to a specified maximum (denoted as \( k_{\text{max}} \)), find the minimal \( N \) that is a product-sum number for that \( k \). Finally, sum all unique minimal \( N \) values found for each \( k \).

Let's dissect the provided Python script:

def prodsum(p, s, c, start):
    k = p - s + c  # product - sum + number of factors = k
    if k < kmax:
        if p < n[k]:
            n[k] = p  # Update if we found a smaller product-sum
        for i in range(start, kmax//p * 2 + 1):
            prodsum(p*i, s+i, c+1, i)

kmax = int(input())+1
n = [2*kmax] * kmax
prodsum(1, 1, 1, 2)
print(sum(set(n[2:])))
1. Function prodsum

This is a recursive function designed to explore all possible combinations of factors that can form product-sum numbers. Here's what each parameter represents:

Inside the Function:

Calculate \( k \)

\[ k = p - s + c \]

This formula derives from rearranging the product-sum equation:

\[ N = p = s \Rightarrow p - s = 0 \Rightarrow k = c \]

However, when introducing additional 1's into the factors (which don't change the product but increase the sum), \( k \) adjusts accordingly.

Check if \( k \) is within bounds

The function only processes combinations where \( k < k_{\text{max}} \). This ensures we only consider relevant \( k \) values.

Update Minimal Product-Sum \( N \)

If the current product \( p \) is smaller than the previously recorded minimal \( N \) for this \( k \), update it:

if p < n[k]:
    n[k] = p  # Update if we found a smaller product-sum
Recursion to Explore Further Factors

The loop iterates through possible next factors, starting from start to maintain non-decreasing order. The upper limit for the loop is determined by:

\[ \text{upper bound} = \frac{k_{\text{max}}}{p} \times 2 + 1 \]

This ensures that the product doesn't exceed the necessary bounds, optimizing the search.

For each possible next factor \( i \), the function recursively calls itself with updated parameters:

prodsum(p * i, s + i, c + 1, i)
2. Initialization and Execution

Input and Setup

kmax = int(input()) + 1

Reads the maximum \( k \) value from user input and adds 1 to accommodate Python's zero-based indexing.

Initialize the Minimal Product-Sum List

n = [2 * kmax] * kmax

Creates a list n of size kmax, initializing all entries to a high value (2 * kmax). This list will store the minimal \( N \) for each \( k \).

Start the Recursive Search

prodsum(1, 1, 1, 2)

Compute the Final Sum

print(sum(set(n[2:])))
How It Works Together

The prodsum function explores all possible combinations of factors that can produce different \( N \) values for varying \( k \). By recursively multiplying and adding factors, it efficiently navigates through potential product-sum scenarios.

As the recursion progresses, it continuously updates the list n with the smallest \( N \) found for each \( k \). This ensures that by the end of the recursion, n contains the minimal product-sum numbers for all \( k \) up to kmax - 1.

After populating the list n, the script extracts the unique minimal \( N \) values and sums them, providing the desired output.

Example Walkthrough

Let's consider a small example with \( k_{\text{max}} = 12 \):

1. Initialization
kmax = 13
n = [26] * 13  # Since 2 * 13 = 26
2. Starting the Recursion
prodsum(1, 1, 1, 2)

This call begins exploring factor combinations starting with 2.

3. Recursive Calls

The function explores combinations like:

4. Final Sum

After all recursive explorations, suppose n is populated as:

n = [26, 26, 4, 6, 8, 6, 12, 12, 12, 12, 16, 18, 20]

Extracting unique values (excluding the first two):

\[ \{4, 6, 8, 12, 16, 18, 20\} \]

Summing them:

\[ 4 + 6 + 8 + 12 + 16 + 18 + 20 = 84 \]

So, the script would output 84.

HackerRank version

HackerRank Project Euler 88: What is the sum of all the minimal product-sum numbers for $2\le k\le N$ $(10\le N\le 20000$?

Python Source Code

def prodsum(p, s, c, start):
    k = p - s + c  # product - sum + number of factors = k
    if k < kmax:
        if p < n[k]:
            n[k] = p  # Update if we found a smaller product-sum
        for i in range(start, kmax//p * 2 + 1):
            prodsum(p*i, s+i, c+1, i)

kmax = int(input())+1
n = [2*kmax] * kmax
prodsum(1, 1, 1, 2)
print(sum(set(n[2:])))