📌  相关文章
📜  使用数字 A 或 B 可以将 X 和 Y 的最大次数减少到接近 0

📅  最后修改于: 2022-05-13 01:56:06.009000             🧑  作者: Mango

使用数字 A 或 B 可以将 X 和 Y 的最大次数减少到接近 0

给定 4 个整数X, Y, A, B 。在一个动作中,要么将X减少A ,将Y减少B ,要么将X减少B ,将Y减少A 。计算最大可能的移动。给定 4 个整数X, Y, A, B 。一步我们可以使X = XAY = YB或 X = XBY = YA 。计算最大可能的移动总数。

例子:

朴素方法:X 和 Y 的每个值处,我们可以从 X和 Y的最大值中减去AB的最大值,并从XY的最小值中减去AB的最小值,直到XY保持大于零。

有效的方法:给定的问题可以使用对答案技术的二分搜索来解决。

  • 这里的关键思想是,如果对于任意数量的移动N ,如果有可能执行这么多移动,那么我们也可以执行N - 1 移动。
  • 所以我们可以对答案进行二分搜索。固定范围L = 1 和R = 10000000(如果有大整数值,请更改此值)并为每个值 mid = ( L + R )/2 检查我们是否可以执行这么多的移动。如果可能,则移位L = mid + 1,否则R = mid – 1。返回最大可能值。
  • 要检查任何数字 mid,我们必须至少减少 X 和 Y mid * min( A , B ) 并且对于剩余元素,我们可以计算剩余的总值 | A - B |。如果这些值大于中间值,则增加我们的右侧范围,否则减少左侧范围。

执行:

C++
// C++ Program to implement the above approach
 
#include 
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
// 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


Python3
# 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#
// 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


Javascript


输出:
3

时间复杂度: O(log(MAXN)),其中 MAXN 是最大移动次数
辅助空间: O(1)