📌  相关文章
📜  最小化选择两个乘积为X的数字的成本

📅  最后修改于: 2021-05-04 15:01:05             🧑  作者: Mango

先决条件:查找最大和最小素数

给定四个整数A,B,C和X ,任务是最小化选择两个数字NM的成本,以使NM的乘积等于X,即N * M = X。选择数字N和M的成本决定如下:

  1. 对于第一个数字N:
    • 如果N是质数,则成本为A。
    • 如果N是一个复合数,则成本为B。
    • 如果N为1,则成本为C。
  2. 对于第二个数字M(!= 1),成本为M。

例子:

幼稚的方法:找到所有数量的因子,并检查因子是否为质数,从而找到成本并从中选择最小值。

高效的方法: N可能有以下三种可能的情况:

  1. N是素那么第一个数字成本是固定的。为了最小化成本,选择尽可能高的质数,使得N≠X
  2. N是复合数字:类似于上述情况,最大的复合数字除以数字,但不必找到数字本身。为此,找到除以X的最小素数并将其视为M,并计算成本。
  3. N为1:可以形成任何数字(在X = 1时除外),并且在这种情况下M =X

因此,该想法是针对这三种情况计算成本,并在所有情况中找到最小值。为此,使用最小化的Eratosthenes筛网对所有最小质数因子和最大质数因子的列表进行预先计算,并将其存储在数组中。可以从这些数组轻松计算出所有三种情况的成本。

下面是上述方法的实现:

C++
// C++ implementation of
// the above approach
  
#include 
using namespace std;
  
const int MAX = 100000;
  
// max_prime[i] represents maximum prime
// number that divides the number i
int max_prime[MAX];
  
// min_prime[i] represents minimum prime
// number that divides the number i
int min_prime[MAX];
  
// Function to store the minimum
// prime factor and the maximum
// prime factor in two arrays
void sieve(int n)
{
    for (int i = 2; i <= n; ++i) {
  
        // Check for prime number
        // if min_prime[i] > 0,
        // then it is not a prime number
        if (min_prime[i] > 0) {
            continue;
        }
  
        // If i is a prime number,
        // then both minimum and maximum
        // prime numbers that divide
        // the number is the number itself
        min_prime[i] = i;
        max_prime[i] = i;
  
        int j = i + i;
  
        while (j <= n) {
            if (min_prime[j] == 0) {
  
                // If this number is being visited
                // for first time then this divisor
                // must be the smallest prime number
                // that divides this number
                min_prime[j] = i;
            }
  
            // Update prime number till the last
            // prime number that divides this number
  
            // The last prime number that
            // divides this number will be maximum.
            max_prime[j] = i;
            j += i;
        }
    }
}
  
// Function to minimize the cost of finding
// two numbers for every number such that
// the product of those two is equal to X
int findCost(int A, int B, int C, int X)
{
    // Pre-calculation
    sieve(MAX);
  
    int N, M;
  
    // If X == 1, then there is no way to
    // find N and M. Print -1
    if (X == 1) {
        return -1;
    }
  
    // Case 3 is always valid and cost for that
    // is C + X C for choosing 1 and M = X/1
    int min_cost = C + X;
  
    // Case 1
    // N is prime, first number cost is fixed
    // N is max_prime number divides this number
    int cost_for_prime = A;
    N = max_prime[X];
  
    // If X is prime then the maximum prime number
    // is the number itself. For this case,
    // M becomes 1 and this shouldn't be considered.
    if (N != X) {
  
        // Find M for this case
        M = X / N;
  
        // Add cost for the second number also
        cost_for_prime += M;
  
        // Update min_cost, if the
        // cost for prime is minimum
        min_cost = min(min_cost, cost_for_prime);
    }
  
    // Case 2
    // If N is composite
    // For this find the minimum prime number
    // that divides A[i] and consider this as M
    M = min_prime[X];
  
    // Find N for that number
    N = X / M;
  
    // Check if this number is composite or not
    // if N is prime then there is no way
    // to find any composite number that divides X
    // If N = min_prime[N] then N is prime
    if (N != min_prime[N]) {
        int cost_for_comp = B + M;
  
        // Update min_cost, if the
        // cost for the composite is minimum
        min_cost = min(min_cost, cost_for_comp);
    }
  
    return min_cost;
}
  
// Driver code
int main()
{
    int A = 7, B = 11, C = 2, X = 20;
  
    cout << findCost(A, B, C, X) << " ";
    return 0;
}


Java
// Java implementation of the above approach 
class GFG {
      
    static final int MAX = 1000; 
      
    // max_prime[i] represents maximum prime 
    // number that divides the number i 
    static int max_prime[] = new int[MAX]; 
      
    // min_prime[i] represents minimum prime 
    // number that divides the number i 
    static int min_prime[] = new int[MAX]; 
      
    // Function to store the minimum 
    // prime factor and the maximum 
    // prime factor in two arrays 
    static void sieve(int n) 
    { 
        for (int i = 2; i < n; ++i) { 
      
            // Check for prime number 
            // if min_prime[i] > 0, 
            // then it is not a prime number 
            if (min_prime[i] > 0) { 
                continue; 
            } 
      
            // If i is a prime number, 
            // then both minimum and maximum 
            // prime numbers that divide 
            // the number is the number itself 
            min_prime[i] = i; 
            max_prime[i] = i; 
      
            int j = i + i; 
      
            while (j < n) { 
                if (min_prime[j] == 0) { 
      
                    // If this number is being visited 
                    // for first time then this divisor 
                    // must be the smallest prime number 
                    // that divides this number 
                    min_prime[j] = i; 
                } 
      
                // Update prime number till the last 
                // prime number that divides this number 
      
                // The last prime number that 
                // divides this number will be maximum. 
                max_prime[j] = i; 
                j += i; 
            } 
        } 
    } 
      
    // Function to minimize the cost of finding 
    // two numbers for every number such that 
    // the product of those two is equal to X 
    static int findCost(int A, int B, int C, int X) 
    { 
        // Pre-calculation 
        sieve(MAX); 
      
        int N, M; 
      
        // If X == 1, then there is no way to 
        // find N and M. Print -1 
        if (X == 1) { 
            return -1; 
        } 
      
        // Case 3 is always valid and cost for that 
        // is C + X C for choosing 1 and M = X/1 
        int min_cost = C + X; 
      
        // Case 1 
        // N is prime, first number cost is fixed 
        // N is max_prime number divides this number 
        int cost_for_prime = A; 
        N = max_prime[X]; 
      
        // If X is prime then the maximum prime number 
        // is the number itself. For this case, 
        // M becomes 1 and this shouldn't be considered. 
        if (N != X) { 
      
            // Find M for this case 
            M = X / N; 
      
            // Add cost for the second number also 
            cost_for_prime += M; 
      
            // Update min_cost, if the 
            // cost for prime is minimum 
            min_cost = Math.min(min_cost, cost_for_prime); 
        } 
      
        // Case 2 
        // If N is composite 
        // For this find the minimum prime number 
        // that divides A[i] and consider this as M 
        M = min_prime[X]; 
      
        // Find N for that number 
        N = X / M; 
      
        // Check if this number is composite or not 
        // if N is prime then there is no way 
        // to find any composite number that divides X 
        // If N = min_prime[N] then N is prime 
        if (N != min_prime[N]) { 
            int cost_for_comp = B + M; 
      
            // Update min_cost, if the 
            // cost for the composite is minimum 
            min_cost = Math.min(min_cost, cost_for_comp); 
        } 
      
        return min_cost; 
    } 
      
    // Driver code 
    public static void main (String[] args)
    { 
        int A = 7, B = 11, C = 2, X = 20; 
      
        System.out.println(findCost(A, B, C, X)); 
    } 
  
}
  
// This code is contributed by AnkitRai01


Python3
# Python3 implementation of 
# the above approach 
  
MAX = 10000; 
  
# max_prime[i] represents maximum prime 
# number that divides the number i 
max_prime = [0]*MAX; 
  
# min_prime[i] represents minimum prime 
# number that divides the number i 
min_prime = [0]*MAX; 
  
# Function to store the minimum 
# prime factor and the maximum 
# prime factor in two arrays 
def sieve(n) :
  
    for i in range(2, n) :
  
        # Check for prime number 
        # if min_prime[i] > 0, 
        # then it is not a prime number 
        if (min_prime[i] > 0) :
            continue; 
  
        # If i is a prime number, 
        # then both minimum and maximum 
        # prime numbers that divide 
        # the number is the number itself 
        min_prime[i] = i; 
        max_prime[i] = i; 
  
        j = i + i; 
  
        while (j < n) :
            if (min_prime[j] == 0) :
  
                # If this number is being visited 
                # for first time then this divisor 
                # must be the smallest prime number 
                # that divides this number 
                min_prime[j] = i; 
  
            # Update prime number till the last 
            # prime number that divides this number 
  
            # The last prime number that 
            # divides this number will be maximum. 
            max_prime[j] = i; 
            j += i; 
  
# Function to minimize the cost of finding 
# two numbers for every number such that 
# the product of those two is equal to X 
def findCost(A, B, C, X) : 
  
    # Pre-calculation 
    sieve(MAX); 
  
    # If X == 1, then there is no way to 
    # find N and M. Print -1 
    if (X == 1) :
        return -1; 
  
    # Case 3 is always valid and cost for that 
    # is C + X C for choosing 1 and M = X/1 
    min_cost = C + X; 
  
    # Case 1 
    # N is prime, first number cost is fixed 
    # N is max_prime number divides this number 
    cost_for_prime = A; 
    N = max_prime[X]; 
  
    # If X is prime then the maximum prime number 
    # is the number itself. For this case, 
    # M becomes 1 and this shouldn't be considered. 
    if (N != X) :
  
        # Find M for this case 
        M = X // N; 
  
        # Add cost for the second number also 
        cost_for_prime += M; 
  
        # Update min_cost, if the 
        # cost for prime is minimum 
        min_cost = min(min_cost, cost_for_prime);
  
    # Case 2 
    # If N is composite 
    # For this find the minimum prime number 
    # that divides A[i] and consider this as M 
    M = min_prime[X]; 
  
    # Find N for that number 
    N = X // M; 
  
    # Check if this number is composite or not 
    # if N is prime then there is no way 
    # to find any composite number that divides X 
    # If N = min_prime[N] then N is prime 
    if (N != min_prime[N]) :
        cost_for_comp = B + M; 
  
        # Update min_cost, if the 
        # cost for the composite is minimum 
        min_cost = min(min_cost, cost_for_comp); 
      
    return min_cost; 
  
# Driver code 
if __name__ == "__main__" : 
  
    A = 7; B = 11; C = 2; X = 20; 
  
    print(findCost(A, B, C, X)) ; 
  
    # This code is contributed by AnkitRai01


C#
// C# implementation of the above approach 
using System;
  
class GFG {
      
    static int MAX = 1000; 
      
    // max_prime[i] represents maximum prime 
    // number that divides the number i 
    static int []max_prime = new int[MAX]; 
      
    // min_prime[i] represents minimum prime 
    // number that divides the number i 
    static int []min_prime = new int[MAX]; 
      
    // Function to store the minimum 
    // prime factor and the maximum 
    // prime factor in two arrays 
    static void sieve(int n) 
    { 
        for (int i = 2; i < n; ++i) { 
      
            // Check for prime number 
            // if min_prime[i] > 0, 
            // then it is not a prime number 
            if (min_prime[i] > 0) { 
                continue; 
            } 
      
            // If i is a prime number, 
            // then both minimum and maximum 
            // prime numbers that divide 
            // the number is the number itself 
            min_prime[i] = i; 
            max_prime[i] = i; 
      
            int j = i + i; 
      
            while (j < n) { 
                if (min_prime[j] == 0) { 
      
                    // If this number is being visited 
                    // for first time then this divisor 
                    // must be the smallest prime number 
                    // that divides this number 
                    min_prime[j] = i; 
                } 
      
                // Update prime number till the last 
                // prime number that divides this number 
      
                // The last prime number that 
                // divides this number will be maximum. 
                max_prime[j] = i; 
                j += i; 
            } 
        } 
    } 
      
    // Function to minimize the cost of finding 
    // two numbers for every number such that 
    // the product of those two is equal to X 
    static int findCost(int A, int B, int C, int X) 
    { 
        // Pre-calculation 
        sieve(MAX); 
      
        int N, M; 
      
        // If X == 1, then there is no way to 
        // find N and M. Print -1 
        if (X == 1) { 
            return -1; 
        } 
      
        // Case 3 is always valid and cost for that 
        // is C + X C for choosing 1 and M = X/1 
        int min_cost = C + X; 
      
        // Case 1 
        // N is prime, first number cost is fixed 
        // N is max_prime number divides this number 
        int cost_for_prime = A; 
        N = max_prime[X]; 
      
        // If X is prime then the maximum prime number 
        // is the number itself. For this case, 
        // M becomes 1 and this shouldn't be considered. 
        if (N != X) { 
      
            // Find M for this case 
            M = X / N; 
      
            // Add cost for the second number also 
            cost_for_prime += M; 
      
            // Update min_cost, if the 
            // cost for prime is minimum 
            min_cost = Math.Min(min_cost, cost_for_prime); 
        } 
      
        // Case 2 
        // If N is composite 
        // For this find the minimum prime number 
        // that divides A[i] and consider this as M 
        M = min_prime[X]; 
      
        // Find N for that number 
        N = X / M; 
      
        // Check if this number is composite or not 
        // if N is prime then there is no way 
        // to find any composite number that divides X 
        // If N = min_prime[N] then N is prime 
        if (N != min_prime[N]) { 
            int cost_for_comp = B + M; 
      
            // Update min_cost, if the 
            // cost for the composite is minimum 
            min_cost = Math.Min(min_cost, cost_for_comp); 
        } 
      
        return min_cost; 
    } 
      
    // Driver code 
    public static void Main (string[] args)
    { 
        int A = 7, B = 11, C = 2, X = 20; 
      
        Console.WriteLine(findCost(A, B, C, X)); 
    } 
}
  
// This code is contributed by AnkitRai01


输出:
11