📌  相关文章
📜  找到最大子集的长度,使得所有元素都是成对互质

📅  最后修改于: 2021-09-17 16:08:38             🧑  作者: 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


Javascript


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


Javascript


输出:
6

有效的方法:
可以优化上述方法,该方法取决于前50个自然数中只有15个素数的事实。因此,数组中的所有数字将仅在这 15 个数字中具有质因数。我们将使用位掩码和动态规划来优化问题。

  • 由于只有 15 个素数,如果素数的索引是该数的因数,请考虑每个数字的15 位表示,其中每位为 1。我们将通过 0 索引来索引素数,这意味着 2 在第 0 个位置 3 在索引 1 等等。
  • 整数变量“掩码”表示子集中已经出现的素因数。如果在掩码中设置了第 i 个位,则第 i 个素因数已经发生,否则不会发生。
  • 递归关系的每一步,该元素要么被包含在子集中,要么不能被包含。如果该元素不包含在子数组中,则只需移动到下一个索引即可。如果包含,则通过在掩码中设置与当前元素的质因子相对应的所有位来更改掩码。当前元素只有在其所有质因数之前都没有出现时才能被包括在内。
  • 仅当与掩码中当前元素的数字对应的位为 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

Javascript


输出:
6

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