Given a positive integer n, find the maximum sum of distinct positive integers not exceeding n such that the LCM of all the selected integers is exactly n.
Examples:
Input: n = 2
Output: 3
Explanation: The valid numbers whose LCM is 2 are 1 and 2, and their sum is 1 + 2 = 3.Input: n = 5
Output: 6
Explanation: The valid numbers whose LCM is 5 are 1 and 5, and their sum is 1 + 5 = 6.
Table of Content
[Naive Approach] Generate All Subsets - O(2^n × n) Time and O(n) Space
The idea is to try every possible subset of numbers from 1 to n. For each subset, we compute its LCM and check whether it equals n. If it does, we compute the sum and update the maximum answer.
#include <bits/stdc++.h>
using namespace std;
int getLcm(int a, int b) {
return (a / __gcd(a, b)) * b;
}
// function to compute LCM of a subset
int findLcm(vector<int> &v) {
int lcm = 1;
// iterate over all elements of subset and compute LCM step by step
for (int x : v) {
lcm = getLcm(lcm, x);
}
return lcm;
}
// function to compute sum of a subset
int getSum(vector<int> &v) {
int sum = 0;
// add all elements of subset
for (int x : v) sum += x;
return sum;
}
int maxSumLCM(int n) {
int maxSum = 0;
// total subsets = 2^n (using bitmasking)
int total = (1 << n);
// iterate over all possible subsets
for (int mask = 1; mask < total; mask++) {
vector<int> subset;
// construct subset from current mask
for (int i = 0; i < n; i++) {
// check if i-th bit is set
if (mask & (1 << i)) {
subset.push_back(i + 1);
}
}
// check if LCM of subset equals n
if (findLcm(subset) == n) {
// compute sum of subset
int sum = getSum(subset);
// update maximum sum
maxSum = max(maxSum, sum);
}
}
return maxSum;
}
int main() {
int n = 5;
cout << maxSumLCM(n);
return 0;
}
import java.util.*;
class GFG {
static int getLcm(int a, int b) {
return (a / gcd(a, b)) * b;
}
static int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
// function to compute LCM of a subset
static int findLcm(ArrayList<Integer> v) {
int lcm = 1;
// iterate over all elements of subset and compute LCM step by step
for (int x : v) {
lcm = getLcm(lcm, x);
}
return lcm;
}
// function to compute sum of a subset
static int getSum(ArrayList<Integer> v) {
int sum = 0;
// add all elements of subset
for (int x : v) sum += x;
return sum;
}
static int maxSumLCM(int n) {
int maxSum = 0;
// total subsets = 2^n (using bitmasking)
int total = (1 << n);
// iterate over all possible subsets
for (int mask = 1; mask < total; mask++) {
ArrayList<Integer> subset = new ArrayList<>();
// construct subset from current mask
for (int i = 0; i < n; i++) {
// check if i-th bit is set
if ((mask & (1 << i)) != 0) {
subset.add(i + 1);
}
}
// check if LCM of subset equals n
if (findLcm(subset) == n) {
// compute sum of subset
int sum = getSum(subset);
// update maximum sum
maxSum = Math.max(maxSum, sum);
}
}
return maxSum;
}
public static void main(String[] args) {
int n = 5;
System.out.println(maxSumLCM(n));
}
}
import math
def getLcm(a, b):
return (a // math.gcd(a, b)) * b
# function to compute LCM of a subset
def findLcm(v):
lcm = 1
# iterate over all elements of subset and compute LCM step by step
for x in v:
lcm = getLcm(lcm, x)
return lcm
# function to compute sum of a subset
def getSum(v):
sum = 0
# add all elements of subset
for x in v:
sum += x
return sum
def maxSumLCM(n):
maxSum = 0
# total subsets = 2^n (using bitmasking)
total = (1 << n)
# iterate over all possible subsets
for mask in range(1, total):
subset = []
# construct subset from current mask
for i in range(n):
# check if i-th bit is set
if mask & (1 << i):
subset.append(i + 1)
# check if LCM of subset equals n
if findLcm(subset) == n:
# compute sum of subset
sum_val = getSum(subset)
# update maximum sum
maxSum = max(maxSum, sum_val)
return maxSum
if __name__ == "__main__":
n = 5
print(maxSumLCM(n))
using System;
using System.Collections.Generic;
class GFG {
static int getLcm(int a, int b) {
return (a / Gcd(a, b)) * b;
}
static int Gcd(int a, int b) {
while (b != 0) {
int t = a % b;
a = b;
b = t;
}
return a;
}
// function to compute LCM of a subset
static int findLcm(List<int> v) {
int lcm = 1;
// iterate over all elements of subset and compute LCM step by step
foreach (int x in v) {
lcm = getLcm(lcm, x);
}
return lcm;
}
// function to compute sum of a subset
static int getSum(List<int> v) {
int sum = 0;
// add all elements of subset
foreach (int x in v) sum += x;
return sum;
}
static int maxSumLCM(int n) {
int maxSum = 0;
// total subsets = 2^n (using bitmasking)
int total = (1 << n);
// iterate over all possible subsets
for (int mask = 1; mask < total; mask++) {
List<int> subset = new List<int>();
// construct subset from current mask
for (int i = 0; i < n; i++) {
// check if i-th bit is set
if ((mask & (1 << i)) != 0) {
subset.Add(i + 1);
}
}
// check if LCM of subset equals n
if (findLcm(subset) == n) {
// compute sum of subset
int sum = getSum(subset);
// update maximum sum
maxSum = Math.Max(maxSum, sum);
}
}
return maxSum;
}
static void Main() {
int n = 5;
Console.WriteLine(maxSumLCM(n));
}
}
function getLcm(a, b) {
function gcd(x, y) {
while (y) {
let t = x % y;
x = y;
y = t;
}
return x;
}
return (a / gcd(a, b)) * b;
}
// function to compute LCM of a subset
function findLcm(v) {
let lcm = 1;
// iterate over all elements of subset and compute LCM step by step
for (let x of v) {
lcm = getLcm(lcm, x);
}
return lcm;
}
// function to compute sum of a subset
function getSum(v) {
let sum = 0;
// add all elements of subset
for (let x of v) sum += x;
return sum;
}
function maxSumLCM(n) {
let maxSum = 0;
// total subsets = 2^n (using bitmasking)
let total = (1 << n);
// iterate over all possible subsets
for (let mask = 1; mask < total; mask++) {
let subset = [];
// construct subset from current mask
for (let i = 0; i < n; i++) {
// check if i-th bit is set
if (mask & (1 << i)) {
subset.push(i + 1);
}
}
// check if LCM of subset equals n
if (findLcm(subset) == n) {
// compute sum of subset
let sum = getSum(subset);
// update maximum sum
maxSum = Math.max(maxSum, sum);
}
}
return maxSum;
}
let n = 5;
console.log(maxSumLCM(n));
Output
6
[Expected Approach] Sum of All Divisors - O(√n) Time and O(1) Space
The key idea is to avoid checking all subsets and use a simple property of LCM. For the LCM to be exactly n, every selected number must be a divisor of n, otherwise it will increase the LCM beyond n. Hence, only divisors are valid choices. Since adding more valid numbers increases the sum without changing the LCM, the optimal solution is to include all divisors of n to maximize the sum.
- Initialize sum = 0
- Iterate from 1 to √n
- If i is a divisor of n:
- Add i to the sum
- Add n / i if it is different from i
- Return the final sum
Consider integer: n = 12
Iterate from 1 to √12 ≈ 3
- For i = 1: 12 % 1 == 0 -> Add: 1 and 12 -> Sum = 13
- For i = 2: 12 % 2 == 0 -> Add: 2 and 6 -> Sum = 21
- For i = 3: 12 % 3 == 0 -> Add: 3 and 4 -> Sum = 28
- For i = 4 to 12: Already covered through pairs -> no new additions
Final Answer:28
#include <bits/stdc++.h>
using namespace std;
int maxSumLCM(int n) {
int sum = 0;
// iterate till square root of n
for (int i = 1; i * i <= n; i++) {
// if i is a divisor
if (n % i == 0) {
sum += i;
// add paired divisor if different
if (i != n / i) {
sum += n / i;
}
}
}
return sum;
}
int main() {
int n = 12;
cout << maxSumLCM(n);
return 0;
}
import java.util.*;
class GFG {
static int maxSumLCM(int n) {
int sum = 0;
// iterate till square root of n
for (int i = 1; i * i <= n; i++) {
// if i is a divisor
if (n % i == 0) {
sum += i;
// add paired divisor if different
if (i != n / i) {
sum += n / i;
}
}
}
return sum;
}
public static void main(String[] args) {
int n = 12;
System.out.println(maxSumLCM(n));
}
}
def maxSumLCM(n):
sum_val = 0
# iterate till square root of n
i = 1
while i * i <= n:
# if i is a divisor
if n % i == 0:
sum_val += i
# add paired divisor if different
if i != n // i:
sum_val += n // i
i += 1
return sum_val
if __name__ == "__main__":
n = 12
print(maxSumLCM(n))
using System;
class GFG {
static int maxSumLCM(int n) {
int sum = 0;
// iterate till square root of n
for (int i = 1; i * i <= n; i++) {
// if i is a divisor
if (n % i == 0) {
sum += i;
// add paired divisor if different
if (i != n / i) {
sum += n / i;
}
}
}
return sum;
}
static void Main() {
int n = 12;
Console.WriteLine(maxSumLCM(n));
}
}
function maxSumLCM(n) {
let sum = 0;
// iterate till square root of n
for (let i = 1; i * i <= n; i++) {
// if i is a divisor
if (n % i === 0) {
sum += i;
// add paired divisor if different
if (i !== Math.floor(n / i)) {
sum += Math.floor(n / i);
}
}
}
return sum;
}
let n = 12;
console.log(maxSumLCM(n));
Output
28