2979. Most Expensive Item That Can Not Be Bought đ
Problem Description
You are given two distinct prime numbers primeOne
and primeTwo
.
Alice and Bob are visiting a market that has an infinite number of items. For any positive integer x
, there exists an item with price x
. Alice wants to buy items from the market to gift to Bob. She has an infinite number of coins in two denominations: primeOne
and primeTwo
.
The key constraint is that Alice can only pay using exact change - she can use any combination of her coins (including using just one type or both types), but she must pay the exact price of the item.
For example, if primeOne = 3
and primeTwo = 5
:
- She can buy an item priced at
3
(using one coin of value 3) - She can buy an item priced at
6
(using two coins of value 3) - She can buy an item priced at
8
(using one coin of value 3 and one coin of value 5) - But she cannot buy an item priced at
7
(no combination of 3s and 5s equals 7)
Your task is to find the most expensive item that Alice cannot buy. In other words, find the largest positive integer that cannot be expressed as a * primeOne + b * primeTwo
where a
and b
are non-negative integers.
The solution uses the Chicken McNugget Theorem, which states that for two coprime positive integers (and distinct primes are always coprime), the largest number that cannot be expressed as their linear combination with non-negative coefficients is primeOne * primeTwo - primeOne - primeTwo
.
Intuition
Let's think about what numbers Alice can make with her coins. If she has coins of value primeOne
and primeTwo
, she can make:
- Any multiple of
primeOne
:primeOne
,2*primeOne
,3*primeOne
, ... - Any multiple of
primeTwo
:primeTwo
,2*primeTwo
,3*primeTwo
, ... - Any combination of both:
a*primeOne + b*primeTwo
wherea, b ⼠0
Since primeOne
and primeTwo
are distinct primes, they are coprime (their greatest common divisor is 1). This is a crucial property.
For small numbers, there will be gaps - numbers that cannot be formed. But as numbers get larger, we'll eventually be able to form all consecutive integers. Why? Because with two coprime numbers, we can eventually "fill in" all the gaps by using different combinations.
The key insight is that once we can form primeOne * primeTwo
, we can form all larger numbers. Here's why:
- From
primeOne * primeTwo
onwards, we can form consecutive sequences of lengthprimeOne
by adding multiples ofprimeOne
- We can also form consecutive sequences of length
primeTwo
by adding multiples ofprimeTwo
- Since
primeOne
andprimeTwo
are coprime, these sequences will eventually overlap and cover all integers
The largest number we cannot form turns out to be exactly primeOne * primeTwo - primeOne - primeTwo
. This is known as the Frobenius number for two coprime integers.
To see why this specific formula works, consider that:
- Numbers of the form
k * primeOne
wherek ⼠primeTwo
can be rewritten usingprimeTwo
as well - Similarly for numbers of the form
k * primeTwo
wherek ⼠primeOne
- The "crossover point" where we can start forming everything is related to
primeOne * primeTwo
- The largest gap before this point is exactly
primeOne * primeTwo - primeOne - primeTwo
Learn more about Math and Dynamic Programming patterns.
Solution Approach
The solution directly applies the Chicken McNugget Theorem (also known as the Frobenius coin problem for two coins).
For two coprime positive integers a
and b
, the theorem states that the largest number that cannot be expressed as a non-negative integer linear combination xa + yb
(where x, y ⼠0
) is exactly a * b - a - b
.
Since our inputs primeOne
and primeTwo
are distinct prime numbers, they are guaranteed to be coprime (their greatest common divisor is 1). This means we can directly apply the theorem.
Implementation:
The solution is remarkably simple - just one line of calculation:
def mostExpensiveItem(self, primeOne: int, primeTwo: int) -> int:
return primeOne * primeTwo - primeOne - primeTwo
Why this formula works:
- Any number
n ⼠primeOne * primeTwo
can be expressed asxa + yb
for some non-negative integersx
andy
- The number
primeOne * primeTwo - primeOne - primeTwo
cannot be expressed this way - This is the largest such number that cannot be expressed
Example walkthrough:
If primeOne = 3
and primeTwo = 5
:
- The formula gives us:
3 * 5 - 3 - 5 = 15 - 3 - 5 = 7
- Indeed, 7 cannot be formed using any combination of 3s and 5s
- All numbers from 8 onwards can be formed:
- 8 = 3 + 5
- 9 = 3 + 3 + 3
- 10 = 5 + 5
- 11 = 3 + 3 + 5
- And so on...
The beauty of this solution is that it requires no loops, no dynamic programming, and no complex calculations - just a direct application of a mathematical theorem that gives us the answer in O(1) time and O(1) space.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example with primeOne = 2
and primeTwo = 7
.
Step 1: Apply the formula According to the Chicken McNugget Theorem:
- Most expensive item Alice cannot buy =
2 Ă 7 - 2 - 7 = 14 - 2 - 7 = 5
Step 2: Verify by checking what Alice CAN buy Let's enumerate what prices Alice can pay with combinations of 2-value and 7-value coins:
- Price 1: Cannot buy (no combination works)
- Price 2: Can buy (1 coin of value 2)
- Price 3: Cannot buy (no combination works)
- Price 4: Can buy (2 coins of value 2)
- Price 5: Cannot buy (no combination of 2s and 7s equals 5)
- Price 6: Can buy (3 coins of value 2)
- Price 7: Can buy (1 coin of value 7)
- Price 8: Can buy (4 coins of value 2)
- Price 9: Can buy (1 coin of value 2 + 1 coin of value 7)
- Price 10: Can buy (5 coins of value 2)
- Price 11: Can buy (2 coins of value 2 + 1 coin of value 7)
- Price 12: Can buy (6 coins of value 2)
Step 3: Confirm the pattern Notice that starting from price 6, we can form all consecutive integers:
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ...
This happens because:
- We can always add another 2-value coin to get the next even number
- We can form any odd number ⼠7 by using one 7-value coin plus some 2-value coins
Step 4: Verify our answer The numbers Alice cannot buy are: 1, 3, and 5. The largest of these is indeed 5, which matches our formula's result!
This demonstrates why the formula primeOne Ă primeTwo - primeOne - primeTwo
gives us exactly the most expensive item that cannot be purchased.
Solution Implementation
1class Solution:
2 def mostExpensiveItem(self, primeOne: int, primeTwo: int) -> int:
3 """
4 Calculate the largest number that cannot be expressed as a non-negative
5 linear combination of two given prime numbers.
6
7 This implements the Frobenius number formula for two coprime integers a and b:
8 Frobenius number = a * b - a - b
9
10 Args:
11 primeOne: First prime number
12 primeTwo: Second prime number
13
14 Returns:
15 The largest integer that cannot be represented as
16 a non-negative combination of primeOne and primeTwo
17 """
18 # Apply the Frobenius number formula: (a * b) - a - b
19 # This gives the largest number that cannot be formed by adding
20 # non-negative multiples of the two prime numbers
21 return primeOne * primeTwo - primeOne - primeTwo
22
1class Solution {
2 /**
3 * Calculates the most expensive item that cannot be obtained
4 * using any combination of two given prime numbers.
5 *
6 * This is based on the Chicken McNugget Theorem (Frobenius Coin Problem):
7 * For two coprime positive integers a and b, the largest number that
8 * cannot be expressed as ax + by (where x, y are non-negative integers)
9 * is ab - a - b.
10 *
11 * @param primeOne The first prime number
12 * @param primeTwo The second prime number
13 * @return The largest value that cannot be obtained as a combination of the two primes
14 */
15 public int mostExpensiveItem(int primeOne, int primeTwo) {
16 // Apply the formula: (primeOne * primeTwo) - primeOne - primeTwo
17 // This gives us the largest number that cannot be represented
18 // as a linear combination of the two prime numbers
19 return primeOne * primeTwo - primeOne - primeTwo;
20 }
21}
22
1class Solution {
2public:
3 /**
4 * Calculates the most expensive item that cannot be purchased
5 * given two prime denominations (Chicken McNugget Theorem).
6 *
7 * For two coprime positive integers, the largest number that
8 * cannot be expressed as their non-negative linear combination
9 * is given by: (primeOne * primeTwo - primeOne - primeTwo)
10 *
11 * @param primeOne First prime number denomination
12 * @param primeTwo Second prime number denomination
13 * @return The largest number that cannot be formed using the two primes
14 */
15 int mostExpensiveItem(int primeOne, int primeTwo) {
16 // Apply the Frobenius formula for two coprime numbers
17 // Result represents the maximum unreachable value
18 int maxUnreachableValue = primeOne * primeTwo - primeOne - primeTwo;
19
20 return maxUnreachableValue;
21 }
22};
23
1/**
2 * Calculates the maximum number of items that cannot be purchased
3 * given two prime numbers representing item prices.
4 * This implements the Frobenius number formula for two coprime integers.
5 *
6 * @param primeOne - The first prime number representing an item price
7 * @param primeTwo - The second prime number representing an item price
8 * @returns The largest monetary amount that cannot be obtained using these two prices
9 */
10function mostExpensiveItem(primeOne: number, primeTwo: number): number {
11 // Apply the Frobenius number formula: (a * b) - a - b
12 // This gives the largest number that cannot be expressed as a linear combination
13 // of the two prime numbers with non-negative integer coefficients
14 return primeOne * primeTwo - primeOne - primeTwo;
15}
16
Time and Space Complexity
The time complexity is O(1)
because the function performs a fixed number of arithmetic operations (one multiplication and two subtractions) regardless of the input values. These basic arithmetic operations take constant time.
The space complexity is O(1)
because the function only uses a constant amount of extra space. It doesn't create any additional data structures or variables that grow with the input size - it simply computes and returns a single integer value directly.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Assuming the Formula Works for All Integer Pairs
The most critical pitfall is incorrectly applying this formula to non-coprime numbers. The Chicken McNugget Theorem only works when the two numbers are coprime (their GCD is 1).
Incorrect assumption:
def mostExpensiveItem(self, numOne: int, numTwo: int) -> int:
# WRONG: This formula doesn't work if numOne and numTwo aren't coprime
return numOne * numTwo - numOne - numTwo
Why it fails: If numOne = 6
and numTwo = 9
(both divisible by 3), the formula gives 6 * 9 - 6 - 9 = 39
. However, you cannot form ANY number that isn't a multiple of 3 using these denominations. The actual answer would be infinity (or undefined) since infinitely many numbers cannot be formed.
Solution: While the problem guarantees distinct primes (which are always coprime), in a general implementation you should verify coprimality:
import math
def mostExpensiveItem(self, numOne: int, numTwo: int) -> int:
if math.gcd(numOne, numTwo) != 1:
# If not coprime, infinitely many numbers cannot be formed
return -1 # or handle this case as specified
return numOne * numTwo - numOne - numTwo
2. Misunderstanding the Problem Constraints
Some might think they need to handle the case where one of the coins has value 1:
Overcomplicated approach:
def mostExpensiveItem(self, primeOne: int, primeTwo: int) -> int:
if primeOne == 1 or primeTwo == 1:
return 0 # Every positive integer can be formed
return primeOne * primeTwo - primeOne - primeTwo
Why it's unnecessary: The problem states we're given two distinct prime numbers. Since 1 is not a prime number, this check is redundant. The smallest possible inputs are 2 and 3.
3. Attempting Dynamic Programming or Iterative Solutions
Given the simplicity of the mathematical formula, implementing a complex solution is both inefficient and error-prone:
Overly complex approach:
def mostExpensiveItem(self, primeOne: int, primeTwo: int) -> int:
# Unnecessary DP approach
max_check = primeOne * primeTwo
dp = [False] * max_check
dp[0] = True
for i in range(1, max_check):
if i >= primeOne and dp[i - primeOne]:
dp[i] = True
if i >= primeTwo and dp[i - primeTwo]:
dp[i] = True
for i in range(max_check - 1, 0, -1):
if not dp[i]:
return i
return 0
Why it's problematic: This uses O(n) time and space where n = primeOne * primeTwo, which is vastly inferior to the O(1) mathematical solution. It also introduces more opportunities for bugs.
4. Integer Overflow Concerns
For very large prime numbers, the multiplication might cause overflow in some languages:
Potential issue in languages with fixed integer sizes:
def mostExpensiveItem(self, primeOne: int, primeTwo: int) -> int:
# In languages like C++ or Java, this might overflow
return primeOne * primeTwo - primeOne - primeTwo
Solution: Python handles arbitrary precision integers automatically, but in other languages you might need to:
- Use long/long long data types
- Check for overflow before calculation
- Rearrange the formula to minimize overflow risk:
(primeOne - 1) * (primeTwo - 1) - 1
The rearranged formula is mathematically equivalent but performs subtraction before multiplication, reducing the maximum intermediate value.
In a binary min heap, the minimum element can be found in:
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
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
Want a Structured Path to Master System Design Too? Donât Miss This!