📌  相关文章
📜  找出最大子集的长度,以使所有元素都是成对共质数

📅  最后修改于: 2021-04-24 04:49:27             🧑  作者: Mango

给定大小为N的数组A ,我们的任务是找到最大子集长度,以使子集中的所有元素都是成对的互质数,即对于x和y中的任意两个元素,其中x和y与gcd(x, y)等于1
注意:所有数组元素均<= 50。

例子:

天真的方法:
为了解决上述问题,我们必须生成所有子集,并针对每个子集检查给定条件是否成立。但是该方法需要O(N 2 * 2 N )时间,并且可以进一步优化。

下面是上述方法的实现:

C++
// C++ implementation to Find the length of the Largest
// subset such that all elements are Pairwise Coprime
#include 
using namespace std;
  
// Function to find the largest subset possible
int largestSubset(int a[], int n)
{
    int answer = 0;
  
    // Iterate through all the subsets
    for (int i = 1; i < (1 << n); i++) {
        vector subset;
  
        /* Check if jth bit in the counter is set */
        for (int j = 0; j < n; j++) {
            if (i & (1 << j))
                subset.push_back(a[j]);
        }
  
        bool flag = true;
  
        for (int j = 0; j < subset.size(); j++) {
            for (int k = j + 1; k < subset.size(); k++) {
                // Check if the gcd is not equal to 1
                if (__gcd(subset[j], subset[k]) != 1)
                    flag = false;
            }
        }
  
        if (flag == true)
            // Update the answer with maximum value
            answer = max(answer, (int)subset.size());
    }
  
    // Return the final result
    return answer;
}
  
// Driver code
int main()
{
  
    int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 };
  
    int N = sizeof(A) / sizeof(A[0]);
  
    cout << largestSubset(A, N);
  
    return 0;
}


Java
// Java implementation to find the length 
// of the largest subset such that all 
// elements are Pairwise Coprime 
import java.util.*; 
  
class GFG{
      
static int gcd(int a, int b) 
{ 
      
    // Everything divides 0 
    if (a == 0) 
        return b; 
    if (b == 0) 
        return a; 
      
    // Base case 
    if (a == b) 
        return a; 
      
    // a is greater 
    if (a > b) 
        return gcd(a - b, b);
          
    return gcd(a, b - a); 
} 
  
// Function to find the largest subset possible 
static int largestSubset(int a[], int n) 
{ 
    int answer = 0; 
      
    // Iterate through all the subsets 
    for(int i = 1; i < (1 << n); i++)
    { 
        Vector subset = new Vector();
      
        // Check if jth bit in the counter is set 
        for(int j = 0; j < n; j++) 
        { 
            if ((i & (1 << j)) != 0) 
                subset.add(a[j]); 
        } 
      
        boolean flag = true; 
      
        for(int j = 0; j < subset.size(); j++) 
        { 
            for(int k = j + 1; k < subset.size(); k++)
            {
                  
                // Check if the gcd is not equal to 1 
                if (gcd((int)subset.get(j),
                       (int) subset.get(k)) != 1) 
                    flag = false; 
            } 
        } 
      
        if (flag == true) 
          
            // Update the answer with maximum value 
            answer = Math.max(answer, 
                             (int)subset.size()); 
    } 
      
    // Return the final result 
    return answer; 
} 
  
// Driver code
public static void main(String args[]) 
{ 
    int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 }; 
      
    int N = A.length;
      
    System.out.println(largestSubset(A, N)); 
}
}
  
// This code is contributed by Stream_Cipher


Python3
# Python3 implementation to Find 
# the length of the Largest subset 
# such that all elements are Pairwise Coprime 
import math
  
# Function to find the largest subset possible 
def largestSubset(a, n):
    answer = 0
  
    # Iterate through all the subsets 
    for i in range(1, (1 << n)): 
        subset = []
  
        # Check if jth bit in the counter is set 
        for j in range(0, n): 
            if (i & (1 << j)):
                subset.insert(j, a[j])
  
        flag = True
  
        for j in range(0, len(subset)):
            for k in range(j + 1, len(subset)): 
                  
                # Check if the gcd is not equal to 1 
                if (math.gcd(subset[j], subset[k]) != 1) :
                    flag = False
  
        if (flag == True):
              
            # Update the answer with maximum value 
            answer = max(answer, len(subset))
  
    # Return the final result 
    return answer
  
# Driver code 
A = [ 2, 3, 13, 5, 14, 6, 7, 11 ] 
N = len(A)
print(largestSubset(A, N))
  
# This code is contributed by Sanjit_Prasad


C#
// C# implementation to Find the length
// of the largest subset such that all
// elements are Pairwise Coprime 
using System;
using System.Collections.Generic; 
  
class GFG{
      
static int gcd(int a, int b) 
{ 
      
    // Everything divides 0 
    if (a == 0) 
        return b; 
    if (b == 0) 
        return a; 
      
    // base case 
    if (a == b) 
        return a; 
      
    // a is greater 
    if (a > b) 
        return gcd(a - b, b); 
          
    return gcd(a, b - a); 
} 
  
// Function to find the largest subset possible 
static int largestSubset(int []a, int n) 
{ 
    int answer = 0; 
      
    // Iterate through all the subsets 
    for(int i = 1; i < (1 << n); i++)
    { 
        List subset = new List();
      
        // Check if jth bit in the counter is set
        for(int j = 0; j < n; j++)
        { 
            if ((i & (1 << j)) != 0) 
                subset.Add(a[j]); 
        } 
      
        int flag = 1; 
      
        for(int j = 0; j < subset.Count; j++) 
        { 
            for(int k = j + 1; k < subset.Count; k++)
            { 
                // Check if the gcd is not equal to 1 
                if (gcd((int)subset[j],
                       (int) subset[k]) != 1) 
                    flag = 0; 
            } 
        } 
      
        if (flag == 1) 
          
            // Update the answer with maximum value 
            answer = Math.Max(answer, 
                             (int)subset.Count); 
    } 
      
    // Return the final result 
    return answer; 
} 
  
// Driver code
public static void Main() 
{ 
    int []A = { 2, 3, 13, 5, 14, 6, 7, 11 }; 
      
    int N = A.Length;
      
    Console.WriteLine(largestSubset(A, N)); 
}
}
  
// This code is contributed by Stream_Cipher


C++
// C++ implementation to Find the length of the Largest
// subset such that all elements are Pairwise Coprime
#include 
using namespace std;
  
// Dynamic programming table
int dp[5000][(1 << 10) + 5];
  
// Function to obtain the mask for any integer
int getmask(int val)
{
    int mask = 0;
  
    // List of prime numbers till 50
    int prime[15] = { 2, 3, 5, 7, 11, 13, 17, 19,
                      23, 29, 31, 37, 41, 43, 47 };
  
    // Iterate through all prime numbers to obtain the mask
    for (int i = 0; i < 15; i++) {
        if (val % prime[i] == 0) {
            // Set this prime's bit ON in the mask
            mask = mask | (1 << i);
        }
    }
  
    // Return the mask value
    return mask;
}
  
// Function to count the number of ways
int calculate(int pos, int mask,
              int a[], int n)
{
    if (pos == n || mask == (1 << n - 1))
        return 0;
  
    // Check if subproblem has been solved
    if (dp[pos][mask] != -1)
        return dp[pos][mask];
  
    int size = 0;
  
    // Excluding current element in the subset
    size = max(size, calculate(pos + 1, mask, a, n));
  
    // Check if there are no common prime factors
    // then only this element can be included
    if ((getmask(a[pos]) & mask) == 0) {
  
        // Calculate the new mask if this element is included
        int new_mask = (mask | (getmask(a[pos])));
  
        size = max(size, 1 + calculate(pos + 1, new_mask, a, n));
    }
  
    // Store and return the answer
    return dp[pos][mask] = size;
}
  
// Function to find the count of
// subarray with all digits unique
int largestSubset(int a[], int n)
{
    // Intializing dp
    memset(dp, -1, sizeof(dp));
  
    return calculate(0, 0, a, n);
}
  
// Driver code
int main()
{
  
    int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 };
  
    int N = sizeof(A) / sizeof(A[0]);
  
    cout << largestSubset(A, N);
  
    return 0;
}


Java
// Java implementation to find the length
// of the largest subset such that all 
// elements are Pairwise Coprime 
import java.util.*; 
  
class GFG{
      
// Dynamic programming table 
static int dp[][] = new int [5000][1029];
  
// Function to obtain the mask for any integer 
static int getmask(int val) 
{ 
    int mask = 0; 
      
    // List of prime numbers till 50 
    int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 
                    23, 29, 31, 37, 41, 43, 47 }; 
      
    // Iterate through all prime numbers
    // to obtain the mask 
    for(int i = 0; i < 15; i++) 
    { 
        if (val % prime[i] == 0) 
        {
              
            // Set this prime's bit ON in the mask 
            mask = mask | (1 << i); 
        } 
    } 
      
    // Return the mask value 
    return mask; 
} 
  
// Function to count the number of ways 
static int calculate(int pos, int mask, 
                     int a[], int n) 
{ 
    if (pos == n ||
       mask == (int)(1 << n - 1)) 
        return 0; 
      
    // Check if subproblem has been solved 
    if (dp[pos][mask] != -1) 
        return dp[pos][mask]; 
      
    int size = 0; 
      
    // Excluding current element in the subset 
    size = Math.max(size, calculate(pos + 1,
                                    mask, a, n)); 
      
    // Check if there are no common prime factors 
    // then only this element can be included 
    if ((getmask(a[pos]) & mask) == 0)
    { 
          
        // Calculate the new mask if this
        // element is included 
        int new_mask = (mask | (getmask(a[pos]))); 
      
        size = Math.max(size, 1 + calculate(pos + 1,
                                            new_mask,
                                            a, n)); 
    } 
      
    // Store and return the answer 
    return dp[pos][mask] = size; 
} 
  
// Function to find the count of 
// subarray with all digits unique 
static int largestSubset(int a[], int n) 
{ 
    for(int i = 0; i < 5000; i++)
        Arrays.fill(dp[i], -1);
          
    return calculate(0, 0, a, n); 
} 
  
// Driver code
public static void main(String args[]) 
{ 
    int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 }; 
      
    int N = A.length;
      
    System.out.println(largestSubset(A, N)); 
}
}
  
// This code is contributed by Stream_Cipher


Python
# Python implementation to find the 
# length of the Largest subset such
# that all elements are Pairwise Coprime 
  
# Dynamic programming table 
dp = [[-1] * ((1 << 10) + 5)] * 5000
  
# Function to obtain the mask for any integer 
def getmask(val):
      
    mask = 0
      
    # List of prime numbers till 50 
    prime = [ 2, 3, 5, 7, 11, 13, 17, 19, 
              23, 29, 31, 37, 41, 43, 47 ]
                
    # Iterate through all prime numbers
    # to obtain the mask 
    for i in range(1, 15):
        if val % prime[i] == 0:
              
            # Set this prime's bit ON in the mask 
            mask = mask | (1 << i)
              
    # Return the mask value 
    return mask
      
# Function to count the number of ways 
def calculate(pos, mask, a, n):
      
    if ((pos == n) or (mask == (1 << n - 1))):
        return 0
          
    # Check if subproblem has been solved 
    if dp[pos][mask] != -1:
        return dp[pos][mask]
          
    size = 0
      
    # Excluding current element in the subset
    size = max(size, calculate(pos + 1, 
                               mask, a, n))
                                 
    # Check if there are no common prime factors 
    # then only this element can be included 
    if (getmask(a[pos]) & mask) == 0:
          
        # Calculate the new mask if this
        # element is included
        new_mask = (mask | (getmask(a[pos])))
        size = max(size, 1 + calculate(pos + 1, 
                                       new_mask,
                                       a, n))
    # Store and return the answer 
    dp[pos][mask] = size
    return dp[pos][mask]
  
# Function to find the count of 
# subarray with all digits unique     
def largestSubset(A, n):
      
    return calculate(0, 0, A, n); 
  
# Driver code
A = [ 2, 3, 13, 5, 14, 6, 7, 11 ] 
N = len(A) 
  
print(largestSubset(A, N))
  
# This code is contributed by Stream_Cipher


C#
// C# implementation to find the length 
// of the largest subset such that all
// elements are Pairwise Coprime 
using System; 
  
class GFG{
      
// Dynamic programming table 
static int [,] dp = new int [5000, 1029];
  
// Function to obtain the mask for any integer 
static int getmask(int val) 
{ 
    int mask = 0; 
      
    // List of prime numbers till 50 
    int []prime = { 2, 3, 5, 7, 11, 13, 17, 19, 
                    23, 29, 31, 37, 41, 43, 47 }; 
      
    // Iterate through all prime 
    // numbers to obtain the mask 
    for(int i = 0; i < 15; i++)
    { 
        if (val % prime[i] == 0)
        { 
              
            // Set this prime's bit ON in the mask 
            mask = mask | (1 << i); 
        } 
    } 
      
    // Return the mask value 
    return mask; 
} 
  
// Function to count the number of ways 
static int calculate(int pos, int mask, 
                     int []a, int n) 
{ 
    if (pos == n ||
       mask == (int)(1 << n - 1)) 
        return 0; 
      
    // Check if subproblem has been solved 
    if (dp[pos, mask] != -1) 
        return dp[pos, mask]; 
      
    int size = 0; 
      
    // Excluding current element in the subset 
    size = Math.Max(size, calculate(pos + 1,
                                    mask, a, n)); 
      
    // Check if there are no common prime factors 
    // then only this element can be included 
    if ((getmask(a[pos]) & mask) == 0)
    { 
          
        // Calculate the new mask if 
        // this element is included 
        int new_mask = (mask | (getmask(a[pos]))); 
      
        size = Math.Max(size, 1 + calculate(pos + 1,
                                            new_mask,
                                            a, n)); 
    } 
      
    // Store and return the answer 
    return dp[pos, mask] = size; 
} 
  
// Function to find the count of 
// subarray with all digits unique 
static int largestSubset(int []a, int n) 
{ 
    for(int i = 0; i < 5000; i++)
    {
        for(int j = 0; j < 1029; j++)
            dp[i, j] = -1;
    }
    return calculate(0, 0, a, n); 
} 
  
// Driver code
public static void Main() 
{ 
    int []A = { 2, 3, 13, 5, 14, 6, 7, 11 }; 
      
    int N = A.Length;
      
    Console.WriteLine(largestSubset(A, N)); 
}
}
  
// This code is contributed by Stream_Cipher


输出:
6

高效方法:
可以优化上述方法,并且该方法取决于以下事实:前50个自然数中只有15个素数。因此,数组中的所有数字仅在这15个数字中具有素数。我们将使用位屏蔽和动态编程来优化该问题。

  • 由于仅存在15个质数,因此考虑每个质数的15位表示形式,如果该质数的索引是该数的因子,则每个位为1。我们将通过0索引对素数进行索引,这意味着2在索引1的第0个位置3处,依此类推。
  • 整数变量“ mask ”表示子集中已经出现的主要因子。如果在掩码中设置了第i个位,则表示存在第i个素因数,否则没有发生。
  • 递归关系的每个步骤中,元素可以包含在子集中,也可以不包含。如果该元素未包含在子数组中,则只需移至下一个索引。如果包含它,则通过将与当前元素的质数因子相对应的所有位设置为ON来更改掩码。如果当前元素的所有主要因素以前均未发生,则只能包括该元素。
  • 仅当掩码中与当前元素的数字相对应的位为OFF时,才能满足此条件。

如果我们绘制完整的递归树,则可以观察到正在解决的许多子问题一次又一次地发生。因此,我们使用表dp [] [],使得对于每个索引dp [i] [j],i是元素在数组中的位置,而j是掩码。

下面是上述方法的实现:

C++

// C++ implementation to Find the length of the Largest
// subset such that all elements are Pairwise Coprime
#include 
using namespace std;
  
// Dynamic programming table
int dp[5000][(1 << 10) + 5];
  
// Function to obtain the mask for any integer
int getmask(int val)
{
    int mask = 0;
  
    // List of prime numbers till 50
    int prime[15] = { 2, 3, 5, 7, 11, 13, 17, 19,
                      23, 29, 31, 37, 41, 43, 47 };
  
    // Iterate through all prime numbers to obtain the mask
    for (int i = 0; i < 15; i++) {
        if (val % prime[i] == 0) {
            // Set this prime's bit ON in the mask
            mask = mask | (1 << i);
        }
    }
  
    // Return the mask value
    return mask;
}
  
// Function to count the number of ways
int calculate(int pos, int mask,
              int a[], int n)
{
    if (pos == n || mask == (1 << n - 1))
        return 0;
  
    // Check if subproblem has been solved
    if (dp[pos][mask] != -1)
        return dp[pos][mask];
  
    int size = 0;
  
    // Excluding current element in the subset
    size = max(size, calculate(pos + 1, mask, a, n));
  
    // Check if there are no common prime factors
    // then only this element can be included
    if ((getmask(a[pos]) & mask) == 0) {
  
        // Calculate the new mask if this element is included
        int new_mask = (mask | (getmask(a[pos])));
  
        size = max(size, 1 + calculate(pos + 1, new_mask, a, n));
    }
  
    // Store and return the answer
    return dp[pos][mask] = size;
}
  
// Function to find the count of
// subarray with all digits unique
int largestSubset(int a[], int n)
{
    // Intializing dp
    memset(dp, -1, sizeof(dp));
  
    return calculate(0, 0, a, n);
}
  
// Driver code
int main()
{
  
    int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 };
  
    int N = sizeof(A) / sizeof(A[0]);
  
    cout << largestSubset(A, N);
  
    return 0;
}

Java

// Java implementation to find the length
// of the largest subset such that all 
// elements are Pairwise Coprime 
import java.util.*; 
  
class GFG{
      
// Dynamic programming table 
static int dp[][] = new int [5000][1029];
  
// Function to obtain the mask for any integer 
static int getmask(int val) 
{ 
    int mask = 0; 
      
    // List of prime numbers till 50 
    int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 
                    23, 29, 31, 37, 41, 43, 47 }; 
      
    // Iterate through all prime numbers
    // to obtain the mask 
    for(int i = 0; i < 15; i++) 
    { 
        if (val % prime[i] == 0) 
        {
              
            // Set this prime's bit ON in the mask 
            mask = mask | (1 << i); 
        } 
    } 
      
    // Return the mask value 
    return mask; 
} 
  
// Function to count the number of ways 
static int calculate(int pos, int mask, 
                     int a[], int n) 
{ 
    if (pos == n ||
       mask == (int)(1 << n - 1)) 
        return 0; 
      
    // Check if subproblem has been solved 
    if (dp[pos][mask] != -1) 
        return dp[pos][mask]; 
      
    int size = 0; 
      
    // Excluding current element in the subset 
    size = Math.max(size, calculate(pos + 1,
                                    mask, a, n)); 
      
    // Check if there are no common prime factors 
    // then only this element can be included 
    if ((getmask(a[pos]) & mask) == 0)
    { 
          
        // Calculate the new mask if this
        // element is included 
        int new_mask = (mask | (getmask(a[pos]))); 
      
        size = Math.max(size, 1 + calculate(pos + 1,
                                            new_mask,
                                            a, n)); 
    } 
      
    // Store and return the answer 
    return dp[pos][mask] = size; 
} 
  
// Function to find the count of 
// subarray with all digits unique 
static int largestSubset(int a[], int n) 
{ 
    for(int i = 0; i < 5000; i++)
        Arrays.fill(dp[i], -1);
          
    return calculate(0, 0, a, n); 
} 
  
// Driver code
public static void main(String args[]) 
{ 
    int A[] = { 2, 3, 13, 5, 14, 6, 7, 11 }; 
      
    int N = A.length;
      
    System.out.println(largestSubset(A, N)); 
}
}
  
// This code is contributed by Stream_Cipher

Python

# Python implementation to find the 
# length of the Largest subset such
# that all elements are Pairwise Coprime 
  
# Dynamic programming table 
dp = [[-1] * ((1 << 10) + 5)] * 5000
  
# Function to obtain the mask for any integer 
def getmask(val):
      
    mask = 0
      
    # List of prime numbers till 50 
    prime = [ 2, 3, 5, 7, 11, 13, 17, 19, 
              23, 29, 31, 37, 41, 43, 47 ]
                
    # Iterate through all prime numbers
    # to obtain the mask 
    for i in range(1, 15):
        if val % prime[i] == 0:
              
            # Set this prime's bit ON in the mask 
            mask = mask | (1 << i)
              
    # Return the mask value 
    return mask
      
# Function to count the number of ways 
def calculate(pos, mask, a, n):
      
    if ((pos == n) or (mask == (1 << n - 1))):
        return 0
          
    # Check if subproblem has been solved 
    if dp[pos][mask] != -1:
        return dp[pos][mask]
          
    size = 0
      
    # Excluding current element in the subset
    size = max(size, calculate(pos + 1, 
                               mask, a, n))
                                 
    # Check if there are no common prime factors 
    # then only this element can be included 
    if (getmask(a[pos]) & mask) == 0:
          
        # Calculate the new mask if this
        # element is included
        new_mask = (mask | (getmask(a[pos])))
        size = max(size, 1 + calculate(pos + 1, 
                                       new_mask,
                                       a, n))
    # Store and return the answer 
    dp[pos][mask] = size
    return dp[pos][mask]
  
# Function to find the count of 
# subarray with all digits unique     
def largestSubset(A, n):
      
    return calculate(0, 0, A, n); 
  
# Driver code
A = [ 2, 3, 13, 5, 14, 6, 7, 11 ] 
N = len(A) 
  
print(largestSubset(A, N))
  
# This code is contributed by Stream_Cipher

C#

// C# implementation to find the length 
// of the largest subset such that all
// elements are Pairwise Coprime 
using System; 
  
class GFG{
      
// Dynamic programming table 
static int [,] dp = new int [5000, 1029];
  
// Function to obtain the mask for any integer 
static int getmask(int val) 
{ 
    int mask = 0; 
      
    // List of prime numbers till 50 
    int []prime = { 2, 3, 5, 7, 11, 13, 17, 19, 
                    23, 29, 31, 37, 41, 43, 47 }; 
      
    // Iterate through all prime 
    // numbers to obtain the mask 
    for(int i = 0; i < 15; i++)
    { 
        if (val % prime[i] == 0)
        { 
              
            // Set this prime's bit ON in the mask 
            mask = mask | (1 << i); 
        } 
    } 
      
    // Return the mask value 
    return mask; 
} 
  
// Function to count the number of ways 
static int calculate(int pos, int mask, 
                     int []a, int n) 
{ 
    if (pos == n ||
       mask == (int)(1 << n - 1)) 
        return 0; 
      
    // Check if subproblem has been solved 
    if (dp[pos, mask] != -1) 
        return dp[pos, mask]; 
      
    int size = 0; 
      
    // Excluding current element in the subset 
    size = Math.Max(size, calculate(pos + 1,
                                    mask, a, n)); 
      
    // Check if there are no common prime factors 
    // then only this element can be included 
    if ((getmask(a[pos]) & mask) == 0)
    { 
          
        // Calculate the new mask if 
        // this element is included 
        int new_mask = (mask | (getmask(a[pos]))); 
      
        size = Math.Max(size, 1 + calculate(pos + 1,
                                            new_mask,
                                            a, n)); 
    } 
      
    // Store and return the answer 
    return dp[pos, mask] = size; 
} 
  
// Function to find the count of 
// subarray with all digits unique 
static int largestSubset(int []a, int n) 
{ 
    for(int i = 0; i < 5000; i++)
    {
        for(int j = 0; j < 1029; j++)
            dp[i, j] = -1;
    }
    return calculate(0, 0, a, n); 
} 
  
// Driver code
public static void Main() 
{ 
    int []A = { 2, 3, 13, 5, 14, 6, 7, 11 }; 
      
    int N = A.Length;
      
    Console.WriteLine(largestSubset(A, N)); 
}
}
  
// This code is contributed by Stream_Cipher
输出:
6

时间复杂度: O(N * 15 * 2 15 )