Given 4 integers X, Y, A, B. In one move either decrease X by A and Y by B or decrease X by B and Y by A. Calculate maximum possible moves. Given 4 integers X, Y, A, B. In one move we can make X = X – A and Y = Y – B or X = X – B and Y = Y – A. Calculate maximum total possible moves.
Example:
Input: X = 10, Y = 12, A = 2, B = 5
Output: 3
Explanation: 1st move: X = 8, Y = 7 after subtracting X by A and Y by B
2nd move: X = 6, Y = 2 after subtracting X by A and Y by B
3rd move: X = 1, Y = 0 after subtracting X by B and Y by A
So a total of 3 moves can be performed.Input: X = 1, Y = 1, A = 2, B = 2
Output: 0
Naive Approach: At every value of X and Y we can subtract max of A and B from max of X and Y and subtract min of A and B from min of X and Y until X and Y stays greater than zero.
Efficient Approach: Given problem can be solved using binary search on answer technique.
- The key idea here is that if for any number of moves N if it is possible to perform this many moves then we can also perform N – 1 moves.
- So we can do a binary search over the answer. Fix the range L = 1 and R = 10000000 (Change this if there are large integer values) and for each value mid = (L + R)/2 check if we can perform this much of moves. If possible then shift L = mid + 1, else R = mid – 1. Return the maximum possible value.
- To check for any number mid, we have to decrease X and Y at least mid * min(A, B) and for the remaining element, we can calculate total values for remaining for |A – B|. If these values are greater than mid then increase our right range otherwise decrease the left range.
Implementation:
// C++ Program to implement the above approach #include <bits/stdc++.h> using namespace std;
// Helper function to check if // we can perform Mid number of moves #define MAXN 10000000 // MAXN = 1e7 bool can( int Mid, int X, int Y, int A, int B)
{ // Remove atleast Mid * B from both X and Y
int p1 = X - Mid * B;
int p2 = Y - Mid * B;
// If any value is negative return false.
if (p1 < 0 || p2 < 0) {
return false ;
}
// Calculate remaining values
int k = A - B;
if (k == 0) {
return true ;
}
int val = p1 / k + p2 / k;
// If val >= Mid then it is possible
// to perform this much moves
if (val >= Mid) {
return true ;
}
// else return false
return false ;
} int maxPossibleMoves( int X, int Y, int A, int B)
{ // Initialize a variable to store the answer
int ans = 0;
// Fix the left and right range
int L = 1, R = MAXN;
// Binary Search over the answer
while (L <= R) {
// Check for the middle
// value as the answer
int Mid = (L + R) / 2;
if (can(Mid, X, Y, A, B)) {
// It is possible to perform
// this much moves
L = Mid + 1;
// Maximise the answer
ans = max(ans, Mid);
}
else {
R = Mid - 1;
}
}
// Return answer
return ans;
} // Driver Code int main()
{ int X = 10, Y = 12, A = 2, B = 5;
// Generalise that A >= B
if (A < B) {
swap(A, B);
}
cout << maxPossibleMoves(X, Y, A, B);
} |
// Java program to implement the above approach import java.io.*;
class GFG{
// Helper function to check if // we can perform Mid number of moves static int MAXN = 10000000 ;
static boolean can( int Mid, int X, int Y,
int A, int B)
{ // Remove atleast Mid * B from both X and Y
int p1 = X - Mid * B;
int p2 = Y - Mid * B;
// If any value is negative return false.
if (p1 < 0 || p2 < 0 )
{
return false ;
}
// Calculate remaining values
int k = A - B;
if (k == 0 )
{
return true ;
}
int val = p1 / k + p2 / k;
// If val >= Mid then it is possible
// to perform this much moves
if (val >= Mid)
{
return true ;
}
// Else return false
return false ;
} static int maxPossibleMoves( int X, int Y, int A, int B)
{ // Initialize a variable to store the answer
int ans = 0 ;
// Fix the left and right range
int L = 1 , R = MAXN;
// Binary Search over the answer
while (L <= R)
{
// Check for the middle
// value as the answer
int Mid = (L + R) / 2 ;
if (can(Mid, X, Y, A, B))
{
// It is possible to perform
// this much moves
L = Mid + 1 ;
// Maximise the answer
ans = Math.max(ans, Mid);
}
else
{
R = Mid - 1 ;
}
}
// Return answer
return ans;
} // Driver Code public static void main(String[] args)
{ int X = 10 , Y = 12 , A = 2 , B = 5 ;
// Generalise that A >= B
if (A < B)
{
int temp = A;
A = B;
B = temp;
}
System.out.println(maxPossibleMoves(X, Y, A, B));
} } // This code is contributed by Potta Lokesh |
# Python Program to implement the above approach # Helper function to check if # we can perform Mid number of moves MAXN = 10000000
def can(Mid, X, Y, A, B):
# Remove atleast Mid * B from both X and Y
p1 = X - Mid * B
p2 = Y - Mid * B
# If any value is negative return false.
if (p1 < 0 or p2 < 0 ):
return False
# Calculate remaining values
k = A - B
if (k = = 0 ):
return True
val = p1 / / k + p2 / / k
# If val >= Mid then it is possible
# to perform this much moves
if (val > = Mid):
return True
# else return false
return False
def maxPossibleMoves(X, Y, A, B):
# Initialize a variable to store the answer
ans = 0
# Fix the left and right range
L = 1
R = MAXN
# Binary Search over the answer
while (L < = R):
# Check for the middle
# value as the answer
Mid = (L + R) / / 2
if (can(Mid, X, Y, A, B)):
# It is possible to perform
# this much moves
L = Mid + 1
# Maximise the answer
ans = max (ans, Mid)
else :
R = Mid - 1
# Return answer
return ans
# Driver Code X = 10
Y = 12
A = 2
B = 5
# Generalise that A >= B if (A < B):
tmp = A
A = B
B = tmp
print (maxPossibleMoves(X, Y, A, B))
# This code is contributed by shivanisinghss2110 |
// C# program to implement the above approach using System;
class GFG{
// Helper function to check if // we can perform Mid number of moves static int MAXN = 10000000;
static Boolean can( int Mid, int X, int Y,
int A, int B)
{ // Remove atleast Mid * B from both X and Y
int p1 = X - Mid * B;
int p2 = Y - Mid * B;
// If any value is negative return false.
if (p1 < 0 || p2 < 0)
{
return false ;
}
// Calculate remaining values
int k = A - B;
if (k == 0)
{
return true ;
}
int val = p1 / k + p2 / k;
// If val >= Mid then it is possible
// to perform this much moves
if (val >= Mid)
{
return true ;
}
// Else return false
return false ;
} static int maxPossibleMoves( int X, int Y, int A, int B)
{ // Initialize a variable to store the answer
int ans = 0;
// Fix the left and right range
int L = 1, R = MAXN;
// Binary Search over the answer
while (L <= R)
{
// Check for the middle
// value as the answer
int Mid = (L + R) / 2;
if (can(Mid, X, Y, A, B))
{
// It is possible to perform
// this much moves
L = Mid + 1;
// Maximise the answer
ans = Math.Max(ans, Mid);
}
else
{
R = Mid - 1;
}
}
// Return answer
return ans;
} // Driver Code public static void Main(String[] args)
{ int X = 10, Y = 12, A = 2, B = 5;
// Generalise that A >= B
if (A < B)
{
int temp = A;
A = B;
B = temp;
}
Console.Write(maxPossibleMoves(X, Y, A, B));
} } // This code is contributed by shivanisinghss2110 |
<script> // Javascript Program to implement the above approach // Helper function to check if // we can perform Mid number of moves let MAXN = 10000000; // MAXN = 1e7
function can(Mid, X, Y, A, B)
{ // Remove atleast Mid * B from both X and Y
let p1 = X - Mid * B;
let p2 = Y - Mid * B;
// If any value is negative return false.
if (p1 < 0 || p2 < 0) {
return false ;
}
// Calculate remaining values
let k = A - B;
if (k == 0) {
return true ;
}
let val = Math.floor(p1 / k) + Math.floor(p2 / k);
// If val >= Mid then it is possible
// to perform this much moves
if (val >= Mid) {
return true ;
}
// else return false
return false ;
} function maxPossibleMoves(X, Y, A, B)
{ // Initialize a variable to store the answer
let ans = 0;
// Fix the left and right range
let L = 1,
R = MAXN;
// Binary Search over the answer
while (L <= R)
{
// Check for the middle
// value as the answer
let Mid = Math.floor((L + R) / 2);
if (can(Mid, X, Y, A, B))
{
// It is possible to perform
// this much moves
L = Mid + 1;
// Maximise the answer
ans = Math.max(ans, Mid);
} else {
R = Mid - 1;
}
}
// Return answer
return ans;
} // Driver Code let X = 10, Y = 12,
A = 2,
B = 5;
// Generalise that A >= B if (A < B) {
let temp = A;
A = B;
B = temp;
} document.write(maxPossibleMoves(X, Y, A, B)); // This code is contributed by _saurabh_jaiswal. </script> |
3
Time Complexity: O(log(MAXN)), where MAXN is maximum number of moves
Auxiliary Space: O(1)