📜  数字A,B和C的倍数集中的第K个数字

📅  最后修改于: 2021-04-24 03:37:25             🧑  作者: Mango

给定四个整数ABCK。假设ABC的所有倍数都按排序的顺序存储在集合中,没有重复项,现在的任务是从该集合中找到第K元素。

例子:

方法:此处可以在K上使用二进制搜索来找到集合中的K数字。如果这是A的倍数,让我们找到第K数字。
A的倍数进行二进制搜索,从1K (因为A的最大K倍数可以找到所需集合中的K个数)。
现在,对于值midA的所需倍数将是A * mid (例如X) 。现在的任务是查找这是否是所需集合的K个数。可以如下所示找到它:

现在,根据包含和排除的原理,所需集合中小于X的数字计数将为A1 + B1 + C1 – AB1 – BC1 – CA1 + ABC1
如果count = K – 1 ,则X是必需的答案。
如果计数则该倍数大于X表示设置开始=中间+ 1,否则设置结束=中间– 1

B然后对C执行相同的步骤(如果K个数不是A的倍数)。
由于第K数字必定是ABC的倍数,因此这三个二进制搜索肯定会返回结果。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
#define ll long long int
using namespace std;
  
// Function to return the
// GCD of A and B
int gcd(int A, int B)
{
    if (B == 0)
        return A;
    return gcd(B, A % B);
}
  
// Function to return the
// LCM of A and B
int lcm(int A, int B)
{
    return (A * B) / gcd(A, B);
}
  
// Function to return the Kth element from
// the required set if it a multiple of A
int checkA(int A, int B, int C, int K)
{
    // Start and End for Binary Search
    int start = 1;
    int end = K;
  
    // If no answer found return -1
    int ans = -1;
  
    while (start <= end) {
        int mid = (start + end) / 2;
        int value = A * mid;
  
        int divA = mid - 1;
        int divB = (value % B == 0) ? value / B - 1
                                    : value / B;
        int divC = (value % C == 0) ? value / C - 1
                                    : value / C;
        int divAB = (value % lcm(A, B) == 0)
                        ? value / lcm(A, B) - 1
                        : value / lcm(A, B);
        int divBC = (value % lcm(C, B) == 0)
                        ? value / lcm(C, B) - 1
                        : value / lcm(C, B);
        int divAC = (value % lcm(A, C) == 0)
                        ? value / lcm(A, C) - 1
                        : value / lcm(A, C);
        int divABC = (value % lcm(A, lcm(B, C)) == 0)
                         ? value / lcm(A, lcm(B, C)) - 1
                         : value / lcm(A, lcm(B, C));
  
        // Inclusion and Exclusion
        int elem = divA + divB + divC - divAC
                   - divBC - divAB + divABC;
        if (elem == (K - 1)) {
            ans = value;
            break;
        }
  
        // Multiple should be smaller
        else if (elem > (K - 1)) {
            end = mid - 1;
        }
  
        // Multiple should be bigger
        else {
            start = mid + 1;
        }
    }
  
    return ans;
}
  
// Function to return the Kth element from
// the required set if it a multiple of B
int checkB(int A, int B, int C, int K)
{
    // Start and End for Binary Search
    int start = 1;
    int end = K;
  
    // If no answer found return -1
    int ans = -1;
  
    while (start <= end) {
        int mid = (start + end) / 2;
        int value = B * mid;
  
        int divB = mid - 1;
        int divA = (value % A == 0) ? value / A - 1
                                    : value / A;
        int divC = (value % C == 0) ? value / C - 1
                                    : value / C;
        int divAB = (value % lcm(A, B) == 0)
                        ? value / lcm(A, B) - 1
                        : value / lcm(A, B);
        int divBC = (value % lcm(C, B) == 0)
                        ? value / lcm(C, B) - 1
                        : value / lcm(C, B);
        int divAC = (value % lcm(A, C) == 0)
                        ? value / lcm(A, C) - 1
                        : value / lcm(A, C);
        int divABC = (value % lcm(A, lcm(B, C)) == 0)
                         ? value / lcm(A, lcm(B, C)) - 1
                         : value / lcm(A, lcm(B, C));
  
        // Inclusion and Exclusion
        int elem = divA + divB + divC - divAC
                   - divBC - divAB + divABC;
        if (elem == (K - 1)) {
            ans = value;
            break;
        }
  
        // Multiple should be smaller
        else if (elem > (K - 1)) {
            end = mid - 1;
        }
  
        // Multiple should be bigger
        else {
            start = mid + 1;
        }
    }
  
    return ans;
}
  
// Function to return the Kth element from
// the required set if it a multiple of C
int checkC(int A, int B, int C, int K)
{
    // Start and End for Binary Search
    int start = 1;
    int end = K;
  
    // If no answer found return -1
    int ans = -1;
  
    while (start <= end) {
        int mid = (start + end) / 2;
        int value = C * mid;
  
        int divC = mid - 1;
        int divB = (value % B == 0) ? value / B - 1
                                    : value / B;
        int divA = (value % A == 0) ? value / A - 1
                                    : value / A;
        int divAB = (value % lcm(A, B) == 0)
                        ? value / lcm(A, B) - 1
                        : value / lcm(A, B);
        int divBC = (value % lcm(C, B) == 0)
                        ? value / lcm(C, B) - 1
                        : value / lcm(C, B);
        int divAC = (value % lcm(A, C) == 0)
                        ? value / lcm(A, C) - 1
                        : value / lcm(A, C);
        int divABC = (value % lcm(A, lcm(B, C)) == 0)
                         ? value / lcm(A, lcm(B, C)) - 1
                         : value / lcm(A, lcm(B, C));
  
        // Inclusion and Exclusion
        int elem = divA + divB + divC - divAC
                   - divBC - divAB + divABC;
        if (elem == (K - 1)) {
            ans = value;
            break;
        }
  
        // Multiple should be smaller
        else if (elem > (K - 1)) {
            end = mid - 1;
        }
  
        // Multiple should be bigger
        else {
            start = mid + 1;
        }
    }
  
    return ans;
}
  
// Function to return the Kth element from
// the set of multiples of A, B and C
int findKthMultiple(int A, int B, int C, int K)
{
  
    // Apply binary search on the multiples of A
    int res = checkA(A, B, C, K);
  
    // If the required element is not a
    // multiple of A then the multiples
    // of B and C need to be checked
    if (res == -1)
        res = checkB(A, B, C, K);
  
    // If the required element is neither
    // a multiple of A nor a multiple
    // of B then the multiples of C
    // need to be checked
    if (res == -1)
        res = checkC(A, B, C, K);
  
    return res;
}
  
// Driver code
int main()
{
    int A = 2, B = 4, C = 5, K = 5;
  
    cout << findKthMultiple(A, B, C, K);
  
    return 0;
}


Java
// Java implementation of the above approach 
class GFG 
{
      
    // Function to return the 
    // GCD of A and B 
    static int gcd(int A, int B) 
    { 
        if (B == 0) 
            return A; 
        return gcd(B, A % B); 
    } 
      
    // Function to return the 
    // LCM of A and B 
    static int lcm(int A, int B) 
    { 
        return (A * B) / gcd(A, B); 
    } 
      
    // Function to return the Kth element from 
    // the required set if it a multiple of A 
    static int checkA(int A, int B, int C, int K) 
    { 
        // Start and End for Binary Search 
        int start = 1; 
        int end = K; 
      
        // If no answer found return -1 
        int ans = -1; 
      
        while (start <= end) 
        { 
            int mid = (start + end) / 2; 
            int value = A * mid; 
      
            int divA = mid - 1; 
            int divB = (value % B == 0) ? value / B - 1
                                        : value / B; 
            int divC = (value % C == 0) ? value / C - 1
                                        : value / C; 
            int divAB = (value % lcm(A, B) == 0) ? 
                           value / lcm(A, B) - 1 : 
                           value / lcm(A, B); 
            int divBC = (value % lcm(C, B) == 0) ? 
                           value / lcm(C, B) - 1 : 
                           value / lcm(C, B); 
            int divAC = (value % lcm(A, C) == 0) ? 
                           value / lcm(A, C) - 1 : 
                           value / lcm(A, C); 
            int divABC = (value % lcm(A, lcm(B, C)) == 0) ? 
                            value / lcm(A, lcm(B, C)) - 1 :
                            value / lcm(A, lcm(B, C)); 
      
            // Inclusion and Exclusion 
            int elem = divA + divB + divC - divAC - 
                              divBC - divAB + divABC; 
            if (elem == (K - 1)) 
            { 
                ans = value; 
                break; 
            } 
      
            // Multiple should be smaller 
            else if (elem > (K - 1))
            { 
                end = mid - 1; 
            } 
      
            // Multiple should be bigger 
            else 
            { 
                start = mid + 1; 
            } 
        } 
        return ans; 
    } 
      
    // Function to return the Kth element from 
    // the required set if it a multiple of B 
    static int checkB(int A, int B, int C, int K) 
    { 
        // Start and End for Binary Search 
        int start = 1; 
        int end = K; 
      
        // If no answer found return -1 
        int ans = -1; 
      
        while (start <= end) 
        { 
            int mid = (start + end) / 2; 
            int value = B * mid; 
      
            int divB = mid - 1; 
            int divA = (value % A == 0) ? value / A - 1
                                        : value / A; 
            int divC = (value % C == 0) ? value / C - 1
                                        : value / C; 
            int divAB = (value % lcm(A, B) == 0) ? 
                           value / lcm(A, B) - 1 :
                           value / lcm(A, B); 
            int divBC = (value % lcm(C, B) == 0) ? 
                           value / lcm(C, B) - 1 : 
                           value / lcm(C, B); 
            int divAC = (value % lcm(A, C) == 0) ? 
                           value / lcm(A, C) - 1 : 
                           value / lcm(A, C); 
            int divABC = (value % lcm(A, lcm(B, C)) == 0) ? 
                            value / lcm(A, lcm(B, C)) - 1 : 
                            value / lcm(A, lcm(B, C)); 
      
            // Inclusion and Exclusion 
            int elem = divA + divB + divC - divAC 
                    - divBC - divAB + divABC; 
            if (elem == (K - 1))
            { 
                ans = value; 
                break; 
            } 
      
            // Multiple should be smaller 
            else if (elem > (K - 1))
            { 
                end = mid - 1; 
            } 
      
            // Multiple should be bigger 
            else 
            { 
                start = mid + 1; 
            } 
        } 
        return ans; 
    } 
      
    // Function to return the Kth element from 
    // the required set if it a multiple of C 
    static int checkC(int A, int B, int C, int K) 
    { 
        // Start and End for Binary Search 
        int start = 1; 
        int end = K; 
      
        // If no answer found return -1 
        int ans = -1; 
      
        while (start <= end) 
        { 
            int mid = (start + end) / 2; 
            int value = C * mid; 
      
            int divC = mid - 1; 
            int divB = (value % B == 0) ? value / B - 1
                                        : value / B; 
            int divA = (value % A == 0) ? value / A - 1
                                        : value / A; 
            int divAB = (value % lcm(A, B) == 0) ? 
                           value / lcm(A, B) - 1 : 
                           value / lcm(A, B); 
            int divBC = (value % lcm(C, B) == 0) ? 
                           value / lcm(C, B) - 1 : 
                           value / lcm(C, B); 
            int divAC = (value % lcm(A, C) == 0) ? 
                           value / lcm(A, C) - 1 : 
                           value / lcm(A, C); 
            int divABC = (value % lcm(A, lcm(B, C)) == 0) ? 
                            value / lcm(A, lcm(B, C)) - 1 : 
                            value / lcm(A, lcm(B, C)); 
      
            // Inclusion and Exclusion 
            int elem = divA + divB + divC - divAC - 
                       divBC - divAB + divABC; 
            if (elem == (K - 1)) 
            { 
                ans = value; 
                break; 
            } 
      
            // Multiple should be smaller 
            else if (elem > (K - 1))
            { 
                end = mid - 1; 
            } 
      
            // Multiple should be bigger 
            else
            { 
                start = mid + 1; 
            } 
        } 
        return ans; 
    } 
      
    // Function to return the Kth element from 
    // the set of multiples of A, B and C 
    static int findKthMultiple(int A, int B, int C, int K) 
    { 
      
        // Apply binary search on the multiples of A 
        int res = checkA(A, B, C, K); 
      
        // If the required element is not a 
        // multiple of A then the multiples 
        // of B and C need to be checked 
        if (res == -1) 
            res = checkB(A, B, C, K); 
      
        // If the required element is neither 
        // a multiple of A nor a multiple 
        // of B then the multiples of C 
        // need to be checked 
        if (res == -1) 
            res = checkC(A, B, C, K); 
      
        return res; 
    } 
      
    // Driver code 
    public static void main(String args[])
    { 
        int A = 2, B = 4, C = 5, K = 5; 
      
        System.out.println(findKthMultiple(A, B, C, K)); 
    } 
}
  
// This code is contributed by AnkitRai01


Python3
# Python3 implementation of the approach
  
# Function to return the GCD of A and B
def gcd(A, B):
    if (B == 0):
        return A
    return gcd(B, A % B)
  
# Function to return the
# LCM of A and B
def lcm(A, B):
    return (A * B) // gcd(A, B)
  
# Function to return the Kth element from
# the required set if it a multiple of A
def checkA(A, B, C, K):
      
    # Start and End for Binary Search
    start = 1
    end = K
  
    # If no answer found return -1
    ans = -1
  
    while (start <= end):
        mid = (start + end) // 2
        value = A * mid
  
        divA = mid - 1
  
        divB = value // B - 1 if (value % B == 0) \
                              else value // B
  
        divC = value // C - 1 if (value % C == 0) \
                              else value // C
  
        divAB = value // lcm(A, B) - 1 \
        if (value % lcm(A, B) == 0) \
        else value // lcm(A, B)
  
        divBC = value // lcm(C, B) - 1 \
        if (value % lcm(C, B) == 0) \
        else value // lcm(C, B)
  
        divAC = value // lcm(A, C) - 1 \
        if (value % lcm(A, C) == 0) \
        else value // lcm(A, C)
  
        divABC = value // lcm(A, lcm(B, C)) - 1 \
        if (value % lcm(A, lcm(B, C)) == 0) \
        else value // lcm(A, lcm(B, C))
  
        # Inclusion and Exclusion
        elem = divA + divB + divC - \
               divAC - divBC - divAB + divABC
        if (elem == (K - 1)):
            ans = value
            break
  
        # Multiple should be smaller
        elif (elem > (K - 1)):
            end = mid - 1
  
        # Multiple should be bigger
        else :
            start = mid + 1
  
    return ans
  
# Function to return the Kth element from
# the required set if it a multiple of B
def checkB(A, B, C, K):
      
    # Start and End for Binary Search
    start = 1
    end = K
  
    # If no answer found return -1
    ans = -1
  
    while (start <= end):
        mid = (start + end) // 2
        value = B * mid
  
        divB = mid - 1
  
        if (value % A == 0):
            divA = value // A - 1 
        else: value // A
  
        if (value % C == 0):
            divC = value // C - 1 
        else: value // C
  
        if (value % lcm(A, B) == 0): 
            divAB = value // lcm(A, B) -1 
        else: value // lcm(A, B)
  
        if (value % lcm(C, B) == 0):
            divBC = value // lcm(C, B) -1 
        else: value // lcm(C, B)
  
        if (value % lcm(A, C) == 0):
            divAC = value // lcm(A, C) -1 
        else: value // lcm(A, C)
  
        if (value % lcm(A, lcm(B, C)) == 0):
            divABC = value // lcm(A, lcm(B, C)) - 1 
        else: value // lcm(A, lcm(B, C))
  
        # Inclusion and Exclusion
        elem = divA + divB + divC - \
               divAC - divBC - divAB + divABC
        if (elem == (K - 1)):
            ans = value
            break
  
        # Multiple should be smaller
        elif (elem > (K - 1)):
            end = mid - 1
  
        # Multiple should be bigger
        else :
            start = mid + 1
  
    return ans
  
# Function to return the Kth element from
# the required set if it a multiple of C
def checkC(A, B, C, K):
      
    # Start and End for Binary Search
    start = 1
    end = K
  
    # If no answer found return -1
    ans = -1
  
    while (start <= end):
        mid = (start + end) // 2
        value = C * mid
  
        divC = mid - 1
  
        if (value % B == 0):
            divB = value // B - 1  
        else: value // B
  
        if (value % A == 0):
            divA = value // A - 1  
        else: value // A
  
        if (value % lcm(A, B) == 0): 
            divAB = value // lcm(A, B) -1 
        else: value // lcm(A, B)
  
        if (value % lcm(C, B) == 0):
            divBC = value // lcm(C, B) -1 
        else: value // lcm(C, B)
  
        if (value % lcm(A, C) == 0):
            divAC = value // lcm(A, C) -1  
        else: value // lcm(A, C)
  
        if (value % lcm(A, lcm(B, C)) == 0):
            divABC = value // lcm(A, lcm(B, C)) - 1 
        else: value // lcm(A, lcm(B, C))
  
        # Inclusion and Exclusion
        elem = divA + divB + divC - \
               divAC - divBC - divAB + divABC
        if (elem == (K - 1)):
            ans = value
            break
  
        # Multiple should be smaller
        elif (elem > (K - 1)):
            end = mid - 1
  
        # Multiple should be bigger
        else :
            start = mid + 1
  
    return ans
  
# Function to return the Kth element from
# the set of multiples of A, B and C
def findKthMultiple(A, B, C, K):
  
    # Apply binary search on the multiples of A
    res = checkA(A, B, C, K)
  
    # If the required element is not a
    # multiple of A then the multiples
    # of B and C need to be checked
    if (res == -1):
        res = checkB(A, B, C, K)
  
    # If the required element is neither
    # a multiple of A nor a multiple
    # of B then the multiples of C
    # need to be checked
    if (res == -1):
        res = checkC(A, B, C, K)
  
    return res
  
# Driver code
A = 2
B = 4
C = 5
K = 5
  
print(findKthMultiple(A, B, C, K))
  
# This code is contributed by Mohit Kumar


C#
// C# implementation of the above approach 
using System;
  
class GFG 
{
      
    // Function to return the 
    // GCD of A and B 
    static int gcd(int A, int B) 
    { 
        if (B == 0) 
            return A; 
        return gcd(B, A % B); 
    } 
      
    // Function to return the 
    // LCM of A and B 
    static int lcm(int A, int B) 
    { 
        return (A * B) / gcd(A, B); 
    } 
      
    // Function to return the Kth element from 
    // the required set if it a multiple of A 
    static int checkA(int A, int B, int C, int K) 
    { 
        // Start and End for Binary Search 
        int start = 1; 
        int end = K; 
      
        // If no answer found return -1 
        int ans = -1; 
      
        while (start <= end) 
        { 
            int mid = (start + end) / 2; 
            int value = A * mid; 
      
            int divA = mid - 1; 
            int divB = (value % B == 0) ? value / B - 1
                                        : value / B; 
            int divC = (value % C == 0) ? value / C - 1
                                        : value / C; 
            int divAB = (value % lcm(A, B) == 0) ? 
                           value / lcm(A, B) - 1 : 
                           value / lcm(A, B); 
            int divBC = (value % lcm(C, B) == 0) ? 
                           value / lcm(C, B) - 1 : 
                           value / lcm(C, B); 
            int divAC = (value % lcm(A, C) == 0) ? 
                        value / lcm(A, C) - 1 : 
                        value / lcm(A, C); 
            int divABC = (value % lcm(A, lcm(B, C)) == 0) ? 
                            value / lcm(A, lcm(B, C)) - 1 :
                            value / lcm(A, lcm(B, C)); 
      
            // Inclusion and Exclusion 
            int elem = divA + divB + divC - divAC - 
                              divBC - divAB + divABC; 
            if (elem == (K - 1)) 
            { 
                ans = value; 
                break; 
            } 
      
            // Multiple should be smaller 
            else if (elem > (K - 1))
            { 
                end = mid - 1; 
            } 
      
            // Multiple should be bigger 
            else
            { 
                start = mid + 1; 
            } 
        } 
        return ans; 
    } 
      
    // Function to return the Kth element from 
    // the required set if it a multiple of B 
    static int checkB(int A, int B, int C, int K) 
    { 
        // Start and End for Binary Search 
        int start = 1; 
        int end = K; 
      
        // If no answer found return -1 
        int ans = -1; 
      
        while (start <= end) 
        { 
            int mid = (start + end) / 2; 
            int value = B * mid; 
      
            int divB = mid - 1; 
            int divA = (value % A == 0) ? value / A - 1
                                        : value / A; 
            int divC = (value % C == 0) ? value / C - 1
                                        : value / C; 
            int divAB = (value % lcm(A, B) == 0) ? 
                           value / lcm(A, B) - 1 :
                           value / lcm(A, B); 
            int divBC = (value % lcm(C, B) == 0) ? 
                           value / lcm(C, B) - 1 : 
                           value / lcm(C, B); 
            int divAC = (value % lcm(A, C) == 0) ? 
                           value / lcm(A, C) - 1 : 
                           value / lcm(A, C); 
            int divABC = (value % lcm(A, lcm(B, C)) == 0) ? 
                            value / lcm(A, lcm(B, C)) - 1 : 
                            value / lcm(A, lcm(B, C)); 
      
            // Inclusion and Exclusion 
            int elem = divA + divB + divC - divAC - 
                       divBC - divAB + divABC; 
            if (elem == (K - 1))
            { 
                ans = value; 
                break; 
            } 
      
            // Multiple should be smaller 
            else if (elem > (K - 1))
            { 
                end = mid - 1; 
            } 
      
            // Multiple should be bigger 
            else
            { 
                start = mid + 1; 
            } 
        } 
        return ans; 
    } 
      
    // Function to return the Kth element from 
    // the required set if it a multiple of C 
    static int checkC(int A, int B, int C, int K) 
    { 
        // Start and End for Binary Search 
        int start = 1; 
        int end = K; 
      
        // If no answer found return -1 
        int ans = -1; 
      
        while (start <= end) 
        { 
            int mid = (start + end) / 2; 
            int value = C * mid; 
      
            int divC = mid - 1; 
            int divB = (value % B == 0) ? value / B - 1
                                        : value / B; 
            int divA = (value % A == 0) ? value / A - 1
                                        : value / A; 
            int divAB = (value % lcm(A, B) == 0) ? 
                           value / lcm(A, B) - 1 : 
                           value / lcm(A, B); 
            int divBC = (value % lcm(C, B) == 0) ? 
                           value / lcm(C, B) - 1 : 
                           value / lcm(C, B); 
            int divAC = (value % lcm(A, C) == 0) ? 
                           value / lcm(A, C) - 1 : 
                           value / lcm(A, C); 
            int divABC = (value % lcm(A, lcm(B, C)) == 0) ? 
                            value / lcm(A, lcm(B, C)) - 1 : 
                            value / lcm(A, lcm(B, C)); 
      
            // Inclusion and Exclusion 
            int elem = divA + divB + divC - divAC - 
                       divBC - divAB + divABC; 
            if (elem == (K - 1)) 
            { 
                ans = value; 
                break; 
            } 
      
            // Multiple should be smaller 
            else if (elem > (K - 1))
            { 
                end = mid - 1; 
            } 
      
            // Multiple should be bigger 
            else
            { 
                start = mid + 1; 
            } 
        } 
        return ans; 
    } 
      
    // Function to return the Kth element from 
    // the set of multiples of A, B and C 
    static int findKthMultiple(int A, int B, int C, int K) 
    { 
      
        // Apply binary search on the multiples of A 
        int res = checkA(A, B, C, K); 
      
        // If the required element is not a 
        // multiple of A then the multiples 
        // of B and C need to be checked 
        if (res == -1) 
            res = checkB(A, B, C, K); 
      
        // If the required element is neither 
        // a multiple of A nor a multiple 
        // of B then the multiples of C 
        // need to be checked 
        if (res == -1) 
            res = checkC(A, B, C, K); 
      
        return res; 
    } 
      
    // Driver code 
    public static void Main(String []args)
    { 
        int A = 2, B = 4, C = 5, K = 5; 
      
        Console.WriteLine(findKthMultiple(A, B, C, K)); 
    } 
}
  
// This code is contributed by Arnab Kundu


输出:
8