给定一个由N 个正整数组成的数组arr[] 。任务是找到最短子序列的长度,使得子序列的 GCD 为 1。如果没有子序列的 GCD 为 1,则打印“-1 ”。
例子:
Input: arr[] = {2, 6, 12, 3}
Output: 2
Explanation:
The GCD of 2, 3 = 1, which is the smallest length of subsequence like 2.
Input: arr[] = {2, 4}
Output: -1
Explanation:
GCD of 2, 4 = 2
朴素的方法:想法是生成给定数组的所有可能子序列,并打印 GCD 为 1 且具有最小长度的子序列的长度。如果没有子序列具有 GCD 1,则打印“-1 ”。
时间复杂度: O(2 N )
辅助空间: O(1)
有效的方法:解决这个问题有两个关键观察:
- 只有当两个数的质因数不同时,它们的 GCD 才会等于 1。
- 任何小于10 9 的正数最多可以有 9 个质因数。
例如2×3×5×7×11×13×17×19×23 = 22, 30, 92, 870. 如果我们将此数乘以下一个质数,即 29,它将大于 10^ 9.
请按照以下步骤解决问题:
- 将数字表示为其质因数的乘积。由于我们最多有 9 个质因子,因此我们可以使用 Bitmask 的概念来存储数字的状态。
例如,12 的质因数是 2 和 3。这可以用二进制表示为 11(忽略前面的零),这意味着这个数字有两个质因数。 - 对于输入数组中的每个数字,检查是否有任何其他数字设置了相应的位。这可以使用按位与运算来实现。这个操作的结果是我们解空间的另一种状态。
- 现在使用动态规划的概念来记住状态。这个想法是使用一个数组来存储解空间的状态。这是有效的,因为一次只能设置 9 位,并且大小为 1024 的数组可以捕获解空间的所有状态。
- 每个状态都使用动态规划来存储到达该状态的最短路径。
- 如果任意两个状态的 Bitwise AND 等于0 ,则 GCD 等于1 ,即如果有可能从当前状态到达状态0 ,那么它将具有最小长度的子序列并打印length 否则打印“-1” 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function that finds the prime
// factors of a number
vector findPrimeFactors(int n)
{
// To store the prime factor
vector primeFactors(9, 0);
int j = 0;
// 2s that divide n
if (n % 2 == 0) {
primeFactors[j++] = 2;
while (n % 2 == 0)
n >>= 1;
}
// N must be odd at this point
// Skip one element
for (int i = 3;
i * i <= n; i += 2) {
if (n % i == 0) {
// Update the prime factor
primeFactors[j++] = i;
while (n % i == 0)
n /= i;
}
}
// If n is a prime number
// greater than 2
if (n > 2)
primeFactors[j++] = n;
vector PrimeFactors(j);
for(int i = 0; i < j; i++)
{
PrimeFactors[i] = primeFactors[i];
}
return PrimeFactors;
}
// Function that finds the shortest
// subsequence
void findShortestSubsequence(vector &dp, vector a,
int index, vector primeFactors)
{
int n = a.size();
for (int j = index; j < n; j++) {
int bitmask = 0;
for (int p = 0;
p < primeFactors.size(); p++) {
// Check if the prime factor
// of first number, is also
// the prime factor of the
// rest numbers in array
if ((a[j] % primeFactors[p]) == 0) {
// Set corresponding bit
// of prime factor to 1,
// it means both these
// numbers have the
// same prime factor
bitmask ^= (1 << p);
}
}
for (int i = 0; i < dp.size(); i++) {
// If no states encountered
// so far continue for this
// combination of bits
if (dp[i] == n + 1)
continue;
// Update this state with
// minimum ways to reach
// this state
dp[bitmask & i]
= min(dp[bitmask & i],
dp[i] + 1);
}
}
}
// Function that print the minimum
// length of subsequence
void printMinimumLength(vector a)
{
int Min = a.size() + 1;
for (int i = 0; i < a.size() - 1; i++) {
// Find the prime factors of
// the first number
vector primeFactors
= findPrimeFactors(a[i]);
int n = primeFactors.size();
// Initialize the array with
// maximum steps, size of the
// array + 1 for instance
vector dp(1 << n, a.size() + 1);
// Express the prime factors
// in bit representation
// Total number of set bits is
// equal to the total number
// of prime factors
int setBits = (1 << n) - 1;
// Indicates there is one
// way to reach the number
// under consideration
dp[setBits] = 1;
findShortestSubsequence(dp, a, i + 1,
primeFactors);
// State 0 corresponds
// to gcd of 1
Min = min(dp[0], Min);
}
// If not found such subsequence
// then print "-1"
if (Min == (a.size() + 1))
cout << -1 << endl;
// Else print the length
else
cout << Min << endl;
}
// Driver code
int main()
{
// Given array arr[]
vector arr = { 2, 6, 12, 3 };
// Function Call
printMinimumLength(arr);
return 0;
}
// This code is contributed by divyeshrabadiya07
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class GFG {
// Function that finds the prime
// factors of a number
private static int[] findPrimeFactors(int n)
{
// To store the prime factor
int[] primeFactors = new int[9];
int j = 0;
// 2s that divide n
if (n % 2 == 0) {
primeFactors[j++] = 2;
while (n % 2 == 0)
n >>= 1;
}
// N must be odd at this point
// Skip one element
for (int i = 3;
i * i <= n; i += 2) {
if (n % i == 0) {
// Update the prime factor
primeFactors[j++] = i;
while (n % i == 0)
n /= i;
}
}
// If n is a prime number
// greater than 2
if (n > 2)
primeFactors[j++] = n;
return Arrays.copyOfRange(primeFactors, 0, j);
}
// Function that finds the shortest
// subsequence
private static void
findShortestSubsequence(int[] dp, int[] a,
int index,
int[] primeFactors)
{
int n = a.length;
for (int j = index; j < n; j++) {
int bitmask = 0;
for (int p = 0;
p < primeFactors.length; p++) {
// Check if the prime factor
// of first number, is also
// the prime factor of the
// rest numbers in array
if (a[j] % primeFactors[p] == 0) {
// Set corresponding bit
// of prime factor to 1,
// it means both these
// numbers have the
// same prime factor
bitmask ^= (1 << p);
}
}
for (int i = 0;
i < dp.length; i++) {
// If no states encountered
// so far continue for this
// combination of bits
if (dp[i] == n + 1)
continue;
// Update this state with
// minimum ways to reach
// this state
dp[bitmask & i]
= Math.min(dp[bitmask & i],
dp[i] + 1);
}
}
}
// Function that print the minimum
// length of subsequence
private static void
printMinimumLength(int[] a)
{
int min = a.length + 1;
for (int i = 0;
i < a.length - 1; i++) {
// Find the prime factors of
// the first number
int[] primeFactors
= findPrimeFactors(a[i]);
int n = primeFactors.length;
int[] dp = new int[1 << n];
// Initialize the array with
// maximum steps, size of the
// array + 1 for instance
Arrays.fill(dp, a.length + 1);
// Express the prime factors
// in bit representation
// Total number of set bits is
// equal to the total number
// of prime factors
int setBits = (1 << n) - 1;
// Indicates there is one
// way to reach the number
// under consideration
dp[setBits] = 1;
findShortestSubsequence(dp, a, i + 1,
primeFactors);
// State 0 corresponds
// to gcd of 1
min = Math.min(dp[0], min);
}
// If not found such subsequence
// then print "-1"
if (min == a.length + 1)
System.out.println(-1);
// Else print the length
else
System.out.println(min);
}
// Driver Code
public static void main(String[] args)
{
// Given array arr[]
int[] arr = { 2, 6, 12, 3 };
// Function Call
printMinimumLength(arr);
}
}
Python3
# Python3 program for the above approach
# Function that finds the prime
# factors of a number
def findPrimeFactors(n):
# To store the prime factor
primeFactors = [0 for i in range(9)]
j = 0
# 2s that divide n
if (n % 2 == 0):
primeFactors[j] = 2
j += 1
while (n % 2 == 0):
n >>= 1
# N must be odd at this point
# Skip one element
i = 3
while (i * i <= n):
if (n % i == 0):
# Update the prime factor
primeFactors[j] = i
j += 1
while(n % i == 0):
n //= i
i += 2
# If n is a prime number
# greater than 2
if (n > 2):
primeFactors[j] = n
j += 1
for i in range(0, j + 1):
primeFactors[i] = 0
return primeFactors
# Function that finds the shortest
# subsequence
def findShortestSubsequence(dp, a, index,
primeFactors):
n = len(a)
for j in range(index, n):
bitmask = 0
for p in range(len(primeFactors)):
# Check if the prime factor
# of first number, is also
# the prime factor of the
# rest numbers in array
if (primeFactors[p] != 0 and
a[j] % primeFactors[p] == 0):
# Set corresponding bit
# of prime factor to 1,
# it means both these
# numbers have the
# same prime factor
bitmask ^= (1 << p)
for i in range(len(dp)):
# If no states encountered
# so far continue for this
# combination of bits
if (dp[i] == n + 1):
continue
# Update this state with
# minimum ways to reach
# this state
dp[bitmask & i] = min(dp[bitmask & i],
dp[i] + 1)
# Function that print the minimum
# length of subsequence
def printMinimumLength(a):
mn = len(a) + 1
for i in range(len(a) - 1):
# Find the prime factors of
# the first number
primeFactors = findPrimeFactors(a[i])
n = len(primeFactors)
dp = [0 for i in range(1 << n)]
# Initialize the array with
# maximum steps, size of the
# array + 1 for instance
dp = [len(a) + 1 for i in range(len(dp))]
# Express the prime factors
# in bit representation
# Total number of set bits is
# equal to the total number
# of prime factors
setBits = (1 << n) - 1
# Indicates there is one
# way to reach the number
# under consideration
dp[setBits] = 1
findShortestSubsequence(dp, a, i + 1,
primeFactors)
# State 0 corresponds
# to gcd of 1
mn = min(dp[0], mn)
# If not found such subsequence
# then print "-1"
if (mn == len(a) + 1):
print(-1)
# Else print the length
else:
print(mn)
# Driver Code
if __name__ == '__main__':
# Given array arr[]
arr = [ 2, 6, 12, 3 ]
# Function Call
printMinimumLength(arr)
# This code is contributed by bgangwar59
C#
// C# program for
// the above approach
using System;
class GFG{
// Function that finds the prime
// factors of a number
private static int[] findPrimeFactors(int n)
{
// To store the prime factor
int[] primeFactors = new int[9];
int j = 0;
// 2s that divide n
if (n % 2 == 0)
{
primeFactors[j++] = 2;
while (n % 2 == 0)
n >>= 1;
}
// N must be odd at this point
// Skip one element
for (int i = 3;
i * i <= n; i += 2)
{
if (n % i == 0)
{
// Update the prime factor
primeFactors[j++] = i;
while (n % i == 0)
n /= i;
}
}
// If n is a prime number
// greater than 2
if (n > 2)
primeFactors[j++] = n;
int []temp = new int[j];
Array.Copy(primeFactors, temp, j);
return temp;
}
// Function that finds the shortest
// subsequence
private static void findShortestSubsequence(int[] dp, int[] a,
int index,
int[] primeFactors)
{
int n = a.Length;
for (int j = index; j < n; j++)
{
int bitmask = 0;
for (int p = 0;
p < primeFactors.Length; p++)
{
// Check if the prime factor
// of first number, is also
// the prime factor of the
// rest numbers in array
if (a[j] % primeFactors[p] == 0)
{
// Set corresponding bit
// of prime factor to 1,
// it means both these
// numbers have the
// same prime factor
bitmask ^= (1 << p);
}
}
for (int i = 0;
i < dp.Length; i++)
{
// If no states encountered
// so far continue for this
// combination of bits
if (dp[i] == n + 1)
continue;
// Update this state with
// minimum ways to reach
// this state
dp[bitmask & i] = Math.Min(dp[bitmask & i],
dp[i] + 1);
}
}
}
// Function that print the minimum
// length of subsequence
private static void printMinimumLength(int[] a)
{
int min = a.Length + 1;
for (int i = 0;
i < a.Length - 1; i++)
{
// Find the prime factors of
// the first number
int[] primeFactors = findPrimeFactors(a[i]);
int n = primeFactors.Length;
int[] dp = new int[1 << n];
// Initialize the array with
// maximum steps, size of the
// array + 1 for instance
for(i = 0; i < dp.Length; i++)
dp[i] = a.Length + 1;
// Express the prime factors
// in bit representation
// Total number of set bits is
// equal to the total number
// of prime factors
int setBits = (1 << n) - 1;
// Indicates there is one
// way to reach the number
// under consideration
dp[setBits] = 1;
findShortestSubsequence(dp, a, i + 1,
primeFactors);
// State 0 corresponds
// to gcd of 1
min = Math.Min(dp[0], min);
}
// If not found such subsequence
// then print "-1"
if (min == a.Length + 1)
Console.WriteLine(-1);
// Else print the length
else
Console.WriteLine(min);
}
// Driver Code
public static void Main(String[] args)
{
// Given array []arr
int[] arr = {2, 6, 12, 3};
// Function Call
printMinimumLength(arr);
}
}
// This code is contributed by Rajput-Ji
Javascript
输出
2
时间复杂度: O(N 2 )
辅助空间: O(1)