3610. Minimum Number of Primes to Sum to Target 🔒
Problem Description
You are given two integers n
and m
.
Your task is to select a multiset of prime numbers from the first m
prime numbers such that the sum of the selected primes is exactly n
. You may use each prime number multiple times.
Return the minimum number of prime numbers needed to sum up to n
, or -1 if it is not possible.
For example, with n = 7
and m = 3
(the first 3 primes are 2, 3, 5), you can use the numbers 2 and 5 to reach 7 with two primes. If it's not possible to form n
using these primes (even with repetitions), return -1.
Intuition
This problem is similar to the classic "coin change" problem. Each of the first m
primes can be used any number of times, just like coins of different denominations. The aim is to make the total sum equal to n
using as few of these primes as possible. Since order does not matter and repetitions are allowed, dynamic programming is a natural fit. By thinking about the solutions for smaller sums and how adding another prime can help reach the target, we can build up to the answer for n
. This lets us efficiently find the minimum number of primes needed, or realize that it's impossible with the given set.
Solution Approach
First, generate the first m
prime numbers by checking each number for primality and collecting them until we have enough.
Next, use dynamic programming to solve the problem, much like the "coin change" problem. Define an array f
where f[i]
represents the minimum number of primes needed to sum up to i
. Initialize f[0] = 0
(since zero can always be made using zero primes), and set all other entries in f
to infinity (or a very large value).
Iterate through each prime p
among the first m
primes. For every possible sum i
from p
to n
, update f[i]
as follows:
f[i] = min(f[i], f[i - p] + 1)
This means for each prime, at each step, we decide if adding one more instance of that prime helps achieve the sum with fewer elements.
After processing all the primes, if f[n]
is still infinity, it's impossible to represent n
as the sum of these primes, so return -1. Otherwise, return f[n]
, the minimum count found.
The approach is efficient because it reuses solutions to subproblems (smaller sums) and finds the answer in a bottom-up way.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's use n = 7
and m = 3
as an example. The first 3 primes are [2, 3, 5]
. The goal is to find the minimum number of these primes (repetitions allowed) that sum to exactly 7.
Step 1: Generate the DP Array
- Create an array
f[0...7]
, initialized asf[0]=0
and the rest as infinity.
Step 2: Process Each Prime
Using prime = 2:
- For
i = 2
,f[2] = min(f[2], f[0]+1) = 1
- For
i = 4
,f[4] = min(f[4], f[2]+1) = 2
- For
i = 6
,f[6] = min(f[6], f[4]+1) = 3
Array now: [0, ∞, 1, ∞, 2, ∞, 3, ∞]
Using prime = 3:
- For
i = 3
,f[3] = min(f[3], f[0]+1) = 1
- For
i = 5
,f[5] = min(f[5], f[2]+1) = 2
- For
i = 6
,f[6] = min(3, f[3]+1) = 2
- For
i = 7
,f[7] = min(∞, f[4]+1) = 3
Array now: [0, ∞, 1, 1, 2, 2, 2, 3]
Using prime = 5:
- For
i = 5
,f[5] = min(2, f[0]+1) = 1
- For
i = 6
,f[6] = min(2, f[1]+1) = 2
(no change, sincef[1]=∞
) - For
i = 7
,f[7] = min(3, f[2]+1) = 2
Final array: [0, ∞, 1, 1, 2, 1, 2, 2]
Step 3: Retrieve the Result
f[7] = 2
, meaning the smallest number of primes from [2,3,5]
needed to make 7 is 2.
How?
- 2 + 5 = 7
- 3 + 2 + 2 = 7 (requires 3 primes, which is more)
Conclusion: The minimum count is 2 (e.g., 2 and 5).
Solution Implementation
1import math
2
3# Generate the first M primes using trial division
4primes = []
5num = 2
6M = 1000
7while len(primes) < M:
8 is_prime = True
9 for p in primes:
10 if p * p > num:
11 break
12 if num % p == 0:
13 is_prime = False
14 break
15 if is_prime:
16 primes.append(num)
17 num += 1
18
19class Solution:
20 def minNumberOfPrimes(self, n: int, m: int) -> int:
21 """
22 Returns the minimum number of the first `m` primes that sum up to `n`.
23 If it's impossible, returns -1.
24 """
25 # Helper function for the minimum of two numbers
26 _min = lambda x, y: x if x < y else y
27
28 # Use a large constant to represent infinity
29 inf = float('inf')
30
31 # Initialize DP array: f[i] represents the minimum number of primes summing to i
32 f = [0] + [inf] * n
33
34 # Try each of the first `m` primes as a coin denomination
35 for prime in primes[:m]:
36 for i in range(prime, n + 1):
37 # State transition: either keep current value or use the new prime
38 f[i] = _min(f[i], f[i - prime] + 1)
39
40 # If inf remains, it's not possible to form n; otherwise, return the answer
41 return f[n] if f[n] < inf else -1
42
1import java.util.*;
2
3// This class provides methods to work with prime numbers and compute minimum counts for sum representations.
4class Solution {
5 // Static list storing the first M prime numbers.
6 static List<Integer> primes = new ArrayList<>();
7
8 // Static initialization block to populate the prime list.
9 static {
10 int candidate = 2; // Candidate number to check for primeness.
11 int maxPrimes = 1000; // Number of primes to precompute.
12 while (primes.size() < maxPrimes) {
13 boolean isPrime = true;
14 for (int prime : primes) {
15 // If prime*prime > candidate, no need to check further.
16 if (prime * prime > candidate) {
17 break;
18 }
19 // If divisible, not a prime.
20 if (candidate % prime == 0) {
21 isPrime = false;
22 break;
23 }
24 }
25 // If candidate is prime, add to list.
26 if (isPrime) {
27 primes.add(candidate);
28 }
29 candidate++;
30 }
31 }
32
33 /**
34 * Returns the minimum number of prime numbers (from the first m primes)
35 * that sum up to n. If it's not possible, returns -1.
36 *
37 * This is a classic unbounded knapsack problem.
38 *
39 * @param n the target sum
40 * @param m the number of allowed primes (from the start)
41 * @return minimum count of primes needed to sum to n, or -1 if impossible
42 */
43 public int minNumberOfPrimes(int n, int m) {
44 int[] dp = new int[n + 1]; // dp[i]: min number of primes to sum to i
45 final int INF = 1 << 30; // A large number representing infinity
46 Arrays.fill(dp, INF);
47 dp[0] = 0; // Zero primes needed for sum 0
48
49 // For each of the first m primes
50 for (int prime : primes.subList(0, m)) {
51 // For each sum >= prime
52 for (int sum = prime; sum <= n; sum++) {
53 // Unbounded knapsack: you can use this prime multiple times.
54 dp[s
55um] = Math.min(dp[sum], dp[sum - prime] + 1);
56 }
57 }
58 // If a valid answer was found, return it. Otherwise, return -1.
59 return dp[n] < INF ? dp[n] : -1;
60 }
61}
62
1class Solution {
2public:
3 int minNumberOfPrimes(int n, int m) {
4 // Static vector to cache the smallest 1000 prime numbers
5 static std::vector<int> primes;
6
7 // Initialize the prime list if it's empty
8 if (primes.empty()) {
9 int candidate = 2;
10 int targetPrimeCount = 1000;
11 while ((int)primes.size() < targetPrimeCount) {
12 bool isPrime = true;
13 // Check divisibility by previously found primes (up to sqrt(candidate))
14 for (int prime : primes) {
15 if (prime * prime > candidate) break;
16 if (candidate % prime == 0) {
17 isPrime = false;
18 break;
19 }
20 }
21 if (isPrime) primes.push_back(candidate);
22 ++candidate;
23 }
24 }
25
26 // DP approach: f[i] = minimum number of primes needed to sum up to i
27 std::vector<int> f(n + 1, INT_MAX);
28 f[0] = 0; // Base case
29
30 // Use the first 'm' primes for the solution
31 for (int prime : std::vector<int>(primes.begin(), primes.begin() + m)) {
32 for (int sum = prime; sum <= n; ++sum) {
33 if (f[sum - prime] != INT_MAX) {
34 f[sum] = std::min(f[sum], f[sum - prime] + 1);
35 }
36 }
37 }
38
39 // If a solution exists, return the minimum number of primes, else return -1
40 return f[n] < INT_MAX ? f[n] : -1;
41 }
42};
43
1// Generate the first 1000 prime numbers and store them in the 'primes' array
2const primes: number[] = [];
3let x = 2; // Current number to check for primality
4const M = 1000; // Number of primes to generate
5
6while (primes.length < M) {
7 let isPrime = true;
8 // Check if `x` is divisible by any previously found primes <= sqrt(x)
9 for (const prime of primes) {
10 if (prime * prime > x) break;
11 if (x % prime === 0) {
12 isPrime = false;
13 break;
14 }
15 }
16 if (isPrime) {
17 primes.push(x);
18 }
19 x++;
20}
21
22/**
23 * Computes the minimum number of primes (selected from the first `m` primes)
24 * that sum up to `n`. Returns -1 if no such combination exists.
25 *
26 * @param n - Target sum
27 * @param m - Number of first primes to use
28 * @returns Minimum number of primes needed, or -1 if impossible
29 */
30function minNumberOfPrimes(n: number, m: number): number {
31 const INF = 1e9; // Represent infinity (unreachable state)
32 const dp: number[] = Array(n + 1).fill(INF); // dp[i]: min number of primes to sum to i
33 dp[0] = 0; // Base case: 0 can be formed by 0 primes
34
35 // Only use the first `m` primes
36 for (const prime of primes.slice(0, m)) {
37 // Classic unbounded knapsack dynamic programming loop
38 for (let i = prime; i <= n; i++) {
39 if (dp[i - prime] < INF) {
40 dp[i] = Math.min(dp[i], dp[i - prime] + 1);
41 }
42 }
43 }
44
45 // If not possible return -1, otherwise return the minimum count found
46 return dp[n] < INF ? dp[n] : -1;
47}
48
Time and Space Complexity
- Time Complexity: The overall time complexity is
O(m * n)
. This comes from the nested loops where for each of the firstm
primes, the code loops through possible sums up ton
. - Space Complexity: The space complexity is
O(n + M)
, wheren
is the target sum andM
(here1000
) is the number of precomputed primes. This accounts for thef
array of sizen + 1
and theprimes
list of sizeM
.
Which of the following uses divide and conquer strategy?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!