Maximize sum of GCD of two subsets of given Array
Last Updated :
13 Dec, 2022
Given an array arr[] of positive integers of size N, the task is to divide the array into two non-empty subsets X and Y in such a way that the sum of their GCD turns out to be the maximum possible
Examples:
Input: N = 3, arr[] = {1, 2, 9}
Output: 10
Explanation: We can divide the array as
X = (1, 2) with GCD = 1
Y = (9) with GCD = 9
Maximum sum comes as 10
Input: N = 4, arr[] = {7, 21, 27, 28}
Output: 34
Explanation: Possible divisions :
X= 7, 21, 28 with GCD = 7 and Y = 27 with GCD =27. Sum = 34
X = 7, 21, 27 with GCD = 1 and Y = 28 with GCD =28. Sum = 29
Use the first way for the maximum sum possible i.e., 34.
Approach: The problem can be solved based on the following idea:
To get the maximum GCD sum, keep the highest one in one subset (say X) and the others in another (say Y).
But it can give raise to a case where the second maximum unique element causes the GCD of Y = 1 but the maximum element when considered in Y and the second max in X then the GCD sum may be greater. (Happens when the maximum element when kept with elements of Y subset the GCD is greater than 1 but when 2nd largest was in Y it was 1).
We don’t need to consider for 3rd largest because if both first and second largest are divisible by the GCD then there difference is greater than the GCD[say a] and 3rd largest + a < 1 + largest as largest > 3rd largest+a
- So for gaining max gcd sum we will take gcd of smallest n-2 unique elements.
- Find including which one gives the greater sum.
Follow the below steps to understand better:
- First sort the array arr[].
- Traverse arr from i = 0 to i = N-1 and Find all the unique elements.
- If there was only one element then division in subsets is not possible.
- If only one unique element but more than once, then the same element will be present in both subsets.
- If there are only two unique elements after avoiding repetitions then return their sum.
- Take gcd of all elements except the last two:
- Check which is better to keep alone last or second last element.
- Return the maximum sum.
Below is the code for the above implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int SubMaxGCD( int N, vector< int >& A)
{
if (A.size() == 1)
return -1;
sort(A.begin(), A.end());
vector< int > v;
for ( int i = 0; i < N - 1; ++i) {
if (A[i] == A[i + 1])
continue ;
else
v.push_back(A[i]);
}
v.push_back(A[N - 1]);
if (v.size() == 1) {
return v[0] * 2;
}
if (v.size() == 2) {
return v[0] + v[1];
}
int n = v.size();
int g = v[0];
for ( int i = 1; i < n - 2; ++i) {
g = __gcd(g, v[i]);
}
int gcd_a = __gcd(g, v[n - 2]) + v[n - 1];
int gcd_b = __gcd(g, v[n - 1]) + v[n - 2];
if (gcd_a >= gcd_b)
return gcd_a;
else
return gcd_b;
}
int main()
{
int N = 3;
vector< int > arr = { 1, 2, 9 };
cout << SubMaxGCD(N, arr);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static int gcd( int a, int b)
{
if (b == 0 )
return a;
return gcd(b, a % b);
}
public static int SubMaxGCD( int N, int A[])
{
if (A.length == 1 )
return - 1 ;
Arrays.sort(A);
ArrayList<Integer> v = new ArrayList<>();
for ( int i = 0 ; i < N - 1 ; ++i) {
if (A[i] == A[i + 1 ])
continue ;
else
v.add(A[i]);
}
v.add(A[N - 1 ]);
if (v.size() == 1 ) {
return v.get( 0 ) * 2 ;
}
if (v.size() == 2 ) {
return v.get( 0 ) + v.get( 1 );
}
int n = v.size();
int g = v.get( 0 );
for ( int i = 1 ; i < n - 2 ; ++i) {
g = gcd(g, v.get(i));
}
int gcd_a = gcd(g, v.get(n - 2 )) + v.get(n - 1 );
int gcd_b = gcd(g, v.get(n - 1 )) + v.get(n - 2 );
if (gcd_a >= gcd_b)
return gcd_a;
else
return gcd_b;
}
public static void main(String[] args)
{
int N = 3 ;
int arr[] = { 1 , 2 , 9 };
System.out.print(SubMaxGCD(N, arr));
}
}
|
Python3
def gcd( a, b) :
if (b = = 0 ) :
return a
return gcd(b, a % b)
def SubMaxGCD( N, A) :
if len (A) = = 1 :
return - 1
A.sort()
v = []
for i in range (N - 1 ) :
if A[i] = = A[i + 1 ] :
continue
else :
v.append(A[i])
v.append(A[N - 1 ])
if len (v) = = 1 :
return v[ 0 ] * 2
if len (v) = = 2 :
return v[ 0 ] + v[ 1 ]
n = len (v)
g = v[ 0 ]
for i in range (N - 2 ):
g = gcd(g, v[i])
gcd_a = gcd(g, v[n - 2 ]) + v[n - 1 ]
gcd_b = gcd(g, v[n - 1 ]) + v[n - 2 ]
if gcd_a > = gcd_b :
return gcd_a
else :
return gcd_b
if __name__ = = "__main__" :
N = 3
arr = [ 1 , 2 , 9 ]
print (SubMaxGCD(N, arr))
|
C#
using System;
using System.Collections;
class GFG {
static int gcd( int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
static int SubMaxGCD( int N, int [] A)
{
if (A.Length == 1)
return -1;
Array.Sort(A);
ArrayList v = new ArrayList();
for ( int i = 0; i < N - 1; ++i) {
if (A[i] == A[i + 1])
continue ;
else
v.Add(A[i]);
}
v.Add(A[N - 1]);
if (v.Count == 1) {
return ( int )v[0] * 2;
}
if (v.Count == 2) {
return ( int )v[0] + ( int )v[1];
}
int n = v.Count;
int g = ( int )v[0];
for ( int i = 1; i < n - 2; ++i) {
g = gcd(g, ( int )v[i]);
}
int gcd_a = gcd(g, ( int )v[n - 2]) + ( int )v[n - 1];
int gcd_b = gcd(g, ( int )v[n - 1]) + ( int )v[n - 2];
if (gcd_a >= gcd_b)
return gcd_a;
else
return gcd_b;
}
public static void Main()
{
int N = 3;
int [] arr = { 1, 2, 9 };
Console.Write(SubMaxGCD(N, arr));
}
}
|
Javascript
<script>
const __gcd = (a, b) => {
if (b == 0) return a;
return __gcd(b, a % b);
}
const SubMaxGCD = (N, A) => {
if (A.length == 1)
return -1;
A.sort();
let v = [];
for (let i = 0; i < N - 1; ++i) {
if (A[i] == A[i + 1])
continue ;
else
v.push(A[i]);
}
v.push(A[N - 1]);
if (v.length == 1) {
return v[0] * 2;
}
if (v.length == 2) {
return v[0] + v[1];
}
let n = v.length;
let g = v[0];
for (let i = 1; i < n - 2; ++i) {
g = __gcd(g, v[i]);
}
let gcd_a = __gcd(g, v[n - 2]) + v[n - 1];
let gcd_b = __gcd(g, v[n - 1]) + v[n - 2];
if (gcd_a >= gcd_b)
return gcd_a;
else
return gcd_b;
}
let N = 3;
let arr = [1, 2, 9];
document.write(SubMaxGCD(N, arr));
</script>
|
Time Complexity: O(N * logN)
Auxiliary Space: O(N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...