Number of ways to change the Array such that largest element is LCM of array
Last Updated :
06 Oct, 2023
Given an array
arr[]
, the task is to count the number of the unique arrays can be formed by updating the elements of the given array to any element in the range [1, arr[i]] such that the
Least common multiple of the updated array is equal to the maximum element.
Examples:
Input: arr[] = {6, 3} Output: 13 Explanation: Possible Arrays are - {[1, 1], [1, 2], [2, 1], [2, 2], [1, 3], [3, 1], [3, 3], [4, 1], [4, 2], [5, 1], [6, 1], [6, 2], [6, 3]} Input: arr[] = {1, 4, 3, 2} Output: 15
Approach:
- For the maximum element to be the LCM of the array, we need to fix the maximum element of the array.
- As, we have fixed some number i
as maximum, now for the LCM to be i
, we'll need to ensure that every element in the array is some multiple of i
including i
- We'll find the factors for the number i
and find the number of ways to place them in the array.
- Let's say that the factors of i
be x, y, z
. The count of factors is 3
.
- Let's assume that number of positions that x
be a
means there are a
number of positions that have number in the array which is greater than equal to x
and let y
have b
positions and z
have c
positions.
- Now, number of ways to distribute
x in a
positions, y
in b - a
positions and z
in c - b - a
positions are 3 ^ a * 2 ^ {(b - a)} * 1 ^ {(c - b - a)}
and so on.
- Now, we'll have to subtract those ways which have LCM i
but i
is not there.
- We'll need to subtract 2 ^ b * 1 ^ {(c - b)}
from the ways.
- We'll use BIT(Binary Indexed Tree) to find number of positions greater than some number x
.
Below is the implementation of the above approach:
C++
// C++ implementation to find the
// Number of ways to change the array
// such that maximum element of the
// array is the LCM of the array
#include <bits/stdc++.h>
using namespace std;
// Modulo
const int MOD = 1e9 + 7;
const int N = 1e5 + 5;
// Fenwick tree to find number
// of indexes greater than x
vector<int> BIT(N, 0);
// Function to compute
// x ^ y % MOD
int power(int x, int y)
{
if (x == 0)
return 0;
int ans = 1;
// Loop to compute the
// x^y % MOD
while (y > 0) {
if (y & 1)
ans = (1LL * ans * x) % MOD;
x = (1LL * x * x) % MOD;
y >>= 1;
}
return ans;
}
// Function to update the binary
// indexed tree
void updateBIT(int idx, int val)
{
assert(idx > 0);
while (idx < N) {
BIT[idx] += val;
idx += idx & -idx;
}
}
// Function to find the prefix sum
// upto the current index
int queryBIT(int idx)
{
int ans = 0;
while (idx > 0) {
ans += BIT[idx];
idx -= idx & -idx;
}
return ans;
}
// Function to find the number of
// ways to change the array such
// that the LCM of array is
// maximum element of the array
int numWays(int arr[], int n)
{
int mx = 0;
for (int i = 0; i < n; i++) {
// Updating BIT with the
// frequency of elements
updateBIT(arr[i], 1);
// Maximum element in the array
mx = max(mx, arr[i]);
}
// 1 is for every element
// is 1 in the array;
int ans = 1;
for (int i = 2; i <= mx; i++) {
// Vector for storing the factors
vector<int> factors;
for (int j = 1; j * j <= i; j++) {
// finding factors of i
if (i % j == 0) {
factors.push_back(j);
if (i / j != j)
factors.push_back(i / j);
}
}
// Sorting in descending order
sort(factors.rbegin(), factors.rend());
int cnt = 1;
// for storing number of indexex
// greater than the i - 1 element
int prev = 0;
for (int j = 0; j < factors.size(); j++) {
// Number of remaining factors
int remFactors = int(factors.size()) - j;
// Number of indexes in the array
// with element factor[j] and above
int indexes = n - queryBIT(factors[j] - 1);
// Multiplying count with
// remFcators ^ (indexes - prev)
cnt = (1LL
* cnt
* power(remFactors,
indexes - prev))
% MOD;
prev = max(prev, indexes);
}
// Remove those counts which have
// lcm as i but i is not present
factors.erase(factors.begin());
int toSubtract = 1;
prev = 0;
// Loop to find the count which have
// lcm as i but i is not present
for (int j = 0; j < factors.size(); j++) {
int remFactors = int(factors.size()) - j;
int indexes = n - queryBIT(factors[j] - 1);
toSubtract = (1LL
* toSubtract
* power(remFactors,
indexes - prev));
prev = max(prev, indexes);
}
// Adding cnt - toSubtract to answer
ans = (1LL * ans + cnt
- toSubtract + MOD)
% MOD;
}
return ans;
}
// Driver Code
int main()
{
int arr[] = { 6, 3 };
int n = sizeof(arr) / sizeof(arr[0]);
int ans = numWays(arr, n);
cout << ans << endl;
return 0;
}
Java
import java.util.*;
public class Main {
// Modulo
static final int MOD = 1000000007;
static final int N = 100005;
// Fenwick tree to find number
// of indexes greater than x
static List<Integer> BIT
= new ArrayList<>(Collections.nCopies(N, 0));
// Function to compute
// x ^ y % MOD
static int power(int x, int y)
{
if (x == 0)
return 0;
int ans = 1;
// Loop to compute the
// x^y % MOD
while (y > 0) {
if ((y & 1) != 0)
ans = (int)((1L * ans * x) % MOD);
x = (int)((1L * x * x) % MOD);
y >>= 1;
}
return ans;
}
// Function to update the binary
// indexed tree
static void updateBIT(int idx, int val)
{
assert idx > 0;
while (idx < N) {
BIT.set(idx, BIT.get(idx) + val);
idx += idx & -idx;
}
}
// Function to find the prefix sum
// upto the current index
static int queryBIT(int idx)
{
int ans = 0;
while (idx > 0) {
ans += BIT.get(idx);
idx -= idx & -idx;
}
return ans;
}
// Function to find the number of
// ways to change the array such
// that the LCM of array is
// maximum element of the array
static int numWays(int[] arr, int n)
{
int mx = 0;
for (int i = 0; i < n; i++) {
// Updating BIT with the
// frequency of elements
updateBIT(arr[i], 1);
// Maximum element in the array
mx = Math.max(mx, arr[i]);
}
// 1 is for every element
// is 1 in the array;
int ans = 1;
for (int i = 2; i <= mx; i++) {
// Vector for storing the factors
List<Integer> factors = new ArrayList<>();
for (int j = 1; j * j <= i; j++) {
// finding factors of i
if (i % j == 0) {
factors.add(j);
if (i / j != j)
factors.add(i / j);
}
}
// Sorting in descending order
factors.sort(Collections.reverseOrder());
int cnt = 1;
// for storing number of indexex
// greater than the i - 1 element
int prev = 0;
for (int j = 0; j < factors.size(); j++) {
// Number of remaining factors
int remFactors = factors.size() - j;
// Number of indexes in the array
// with element factor[j] and above
int indexes
= n - queryBIT(factors.get(j) - 1);
// Multiplying count with
// remFcators ^ (indexes - prev)
cnt = (int)((1L * cnt
* power(remFactors,
indexes - prev))
% MOD);
prev = Math.max(prev, indexes);
}
// Remove those counts which have
// lcm as i but i is not present
factors.remove(0);
int toSubtract = 1;
prev = 0;
// Loop to find the count which have
// lcm as i but i is not present
for (int j = 0; j < factors.size(); j++) {
int remFactors = factors.size() - j;
int indexes
= n - queryBIT(factors.get(j) - 1);
toSubtract = (int)((1L * toSubtract
* power(remFactors,
indexes - prev))
% MOD);
prev = Math.max(prev, indexes);
}
// Adding cnt - toSubtract to answer
ans = (int)((1L * ans + cnt - toSubtract + MOD)
% MOD);
}
return ans;
}
// Driver Code
public static void main(String[] args)
{
int[] arr = { 6, 3 };
int n = arr.length;
int ans = numWays(arr, n);
System.out.println(ans);
}
}
// This code is contributed by Samim Hossain Mondal.
Python3
# Python implementation to find the
# Number of ways to change the array
# such that maximum element of the
# array is the LCM of the array
# Modulo
MOD = int(1e9) + 9
MAXN = int(1e5) + 5
# Fenwick tree to find number
# of indexes greater than x
BIT = [0 for _ in range(MAXN)]
# Function to compute
# x ^ y % MOD
def power(x, y):
if x == 0:
return 0
ans = 1
# Loop to compute the
# x ^ y % MOD
while y > 0:
if y % 2 == 1:
ans = (ans * x) % MOD
x = (x * x) % MOD
y = y // 2
return ans
# Function to update the
# Binary Indexed Tree
def updateBIT(idx, val):
# Loop to update the BIT
while idx < MAXN:
BIT[idx] += val
idx += idx & (-idx)
# Function to find
# prefix sum upto idx
def queryBIT(idx):
ans = 0
while idx > 0:
ans += BIT[idx]
idx -= idx & (-idx)
return ans
# Function to find number of ways
# to change the array such that
# MAX of array is same as LCM
def numWays(arr):
mx = 0
# Updating BIT with the
# frequency of elements
for i in arr:
updateBIT(i, 1)
# Maximum element
# in the array
mx = max(mx, i)
ans = 1
for i in range(2, mx + 1):
# For storing factors of i
factors = []
for j in range(1, i + 1):
if j * j > i:
break
# Finding factors of i
if i % j == 0:
factors.append(j)
if i // j != j:
factors.append(i // j)
# Sorting in descending order
factors.sort()
factors.reverse()
# For storing ans
cnt = 1
# For storing number of indexes
# greater than the i - 1 element
prev = 0
for j in range(len(factors)):
# Number of remaining factors
remFactors = len(factors) - j
# Number of indexes in the array
# with element factor[j] and above
indexes = len(arr) - queryBIT(factors[j] - 1)
# Multiplying count with
# remFcators ^ (indexes - prev)
cnt = (cnt * power(remFactors, \
indexes - prev)) % MOD
prev = max(prev, indexes)
# Remove those counts which have
# lcm as i but i is not present
factors.remove(factors[0])
toSubtract = 1
prev = 0
for j in range(len(factors)):
remFactors = len(factors) - j
indexes = len(arr) - queryBIT(factors[j] - 1)
toSubtract = (toSubtract *\
power(remFactors, indexes - prev))
prev = max(prev, indexes)
# Adding cnt - toSubtract to ans;
ans = (ans + cnt - toSubtract + MOD) % MOD;
return ans
# Driver Code
if __name__ == "__main__":
arr = [1, 4, 3, 2]
ans = numWays(arr);
print(ans)
C#
using System;
using System.Collections.Generic;
class MainClass {
// Modulo
const int MOD = 1000000007;
const int N = 100005;
// Fenwick tree to find the number
// of indexes greater than x
static List<int> BIT = new List<int>(new int[N]);
// Function to compute x ^ y % MOD
static int Power(int x, int y) {
if (x == 0)
return 0;
int ans = 1;
// Loop to compute x^y % MOD
while (y > 0) {
if ((y & 1) == 1)
ans = (int)((1L * ans * x) % MOD);
x = (int)((1L * x * x) % MOD);
y >>= 1;
}
return ans;
}
// Function to update the binary
// indexed tree
static void UpdateBIT(int idx, int val) {
if (idx <= 0)
return;
while (idx < N) {
BIT[idx] += val;
idx += idx & -idx;
}
}
// Function to find the prefix sum
// up to the current index
static int QueryBIT(int idx) {
int ans = 0;
while (idx > 0) {
ans += BIT[idx];
idx -= idx & -idx;
}
return ans;
}
// Function to find the number of
// ways to change the array such
// that the LCM of the array is
// the maximum element of the array
static int NumWays(int[] arr, int n) {
int mx = 0;
for (int i = 0; i < n; i++) {
// Updating BIT with the frequency of elements
UpdateBIT(arr[i], 1);
// Maximum element in the array
mx = Math.Max(mx, arr[i]);
}
// 1 is for every element is 1 in the array;
int ans = 1;
for (int i = 2; i <= mx; i++) {
// List for storing the factors
List<int> factors = new List<int>();
for (int j = 1; j * j <= i; j++) {
// Finding factors of i
if (i % j == 0) {
factors.Add(j);
if (i / j != j)
factors.Add(i / j);
}
}
// Sorting in descending order
factors.Sort((a, b) => b.CompareTo(a));
int cnt = 1;
// For storing the number of indexes greater than the i - 1 element
int prev = 0;
for (int j = 0; j < factors.Count; j++) {
// Number of remaining factors
int remFactors = factors.Count - j;
// Number of indexes in the array with element factor[j] and above
int indexes = n - QueryBIT(factors[j] - 1);
// Multiplying count with remFcators ^ (indexes - prev)
cnt = (int)(
(1L * cnt * Power(remFactors, indexes - prev)) % MOD);
prev = Math.Max(prev, indexes);
}
// Remove those counts which have lcm as i but i is not present
factors.RemoveAt(0);
int toSubtract = 1;
prev = 0;
// Loop to find the count which has lcm as i but i is not present
for (int j = 0; j < factors.Count; j++) {
int remFactors = factors.Count - j;
int indexes = n - QueryBIT(factors[j] - 1);
toSubtract = (int)(
(1L * toSubtract * Power(remFactors, indexes - prev)) % MOD);
prev = Math.Max(prev, indexes);
}
// Adding cnt - toSubtract to the answer
ans = (int)((1L * ans + cnt - toSubtract + MOD) % MOD);
}
return ans;
}
public static void Main(string[] args) {
int[] arr = { 6, 3 };
int n = arr.Length;
int ans = NumWays(arr, n);
Console.WriteLine(ans);
}
}
JavaScript
// Modulo
const MOD = 1e9 + 7;
const N = 1e5 + 5;
// Fenwick tree to find the number of indexes greater than x
const BIT = new Array(N).fill(0);
// Function to compute x^y % MOD
function power(x, y) {
if (x === 0) return 0;
let ans = 1;
// Loop to compute x^y % MOD
while (y > 0) {
if (y & 1) ans = (ans * x) % MOD;
x = (x * x) % MOD;
y >>= 1;
}
return ans;
}
// Function to update the binary indexed tree
function updateBIT(idx, val) {
while (idx > 0) {
BIT[idx] += val;
idx += idx & -idx;
}
}
// Function to find the prefix sum up to
// the current index
function queryBIT(idx) {
let ans = 0;
while (idx > 0) {
ans += BIT[idx];
idx -= idx & -idx;
}
return ans;
}
function GFG(arr, n) {
let mx = 0;
for (let i = 0; i < n; i++) {
// Updating BIT with the frequency of elements
updateBIT(arr[i], 1);
// Maximum element in the array
mx = Math.max(mx, arr[i]);
}
// 1 is for every element is 1 in the array
let ans = 1;
for (let i = 2; i <= mx; i++) {
// Vector for storing the factors
const factors = [];
for (let j = 1; j * j <= i; j++) {
// Finding factors of i
if (i % j === 0) {
factors.push(j);
if (i / j !== j) factors.push(i / j);
}
}
// Sorting in descending order
factors.sort((a, b) => b - a);
let cnt = 1;
// For storing the number of indexes greater than
// the (i - 1) element
let prev = 0;
for (let j = 0; j < factors.length; j++) {
// Number of remaining factors
const remFactors = factors.length - j;
// Number of indexes in the array with an element >= factor[j]
const indexes = n - queryBIT(factors[j] - 1);
// Multiplying count with (remFactors ^ (indexes - prev))
cnt = (cnt * power(remFactors, indexes - prev)) % MOD;
prev = Math.max(prev, indexes);
}
// Remove those counts which have LCM as i but i is not present
factors.shift();
let toSubtract = 1;
prev = 0;
// Loop to find the count which have LCM as i but i is not present
for (let j = 0; j < factors.length; j++) {
const remFactors = factors.length - j;
const indexes = n - queryBIT(factors[j] - 1);
toSubtract = (toSubtract * power(remFactors, indexes - prev)) % MOD
prev = Math.max(prev, indexes);
}
// Adding cnt - toSubtract to answer
ans = (ans + cnt - toSubtract + MOD) % MOD;
}
return ans;
}
// Driver Code
const arr = [6, 3];
const n = arr.length;
const ans = GFG(arr, n);
console.log(ans);
Time Complexity:
O(MAX * $\sqrt{MAX}$)
, where
$MAX
is the maximum element in the array.
Similar Reads
Remove an element to minimize the LCM of the given array Given an array arr[] of length N ? 2. The task is to remove an element from the given array such that the LCM of the array after removing it is minimized.Examples: Input: arr[] = {18, 12, 24} Output: 24 Remove 12: LCM(18, 24) = 72 Remove 18: LCM(12, 24) = 24 Remove 24: LCM(12, 18) = 36Input: arr[] =
8 min read
Largest number dividing maximum number of elements in the array Given an array arr[] of length N, the task is to find the largest number dividing the maximum number of elements from the array. Examples: Input: arr[] = {2, 12, 6} Output: 2 1 and 2 are the only integers which divide the maximum number of elements from the array (i.e. all the elements) and 2 is the
4 min read
Largest number in the Array having frequency same as value Given an array arr containing N integers, the task is to find the largest number in the array whose frequency is equal to its value. If no such number exists, then print -1.Examples: Input: arr = [3, 2, 5, 2, 4, 5] Output: 2 Explanation: In this given array frequency of 2 is 2, whereas the frequency
8 min read
Find X such that most Array elements are of form (X + p*K) Given an array arr[] and a number K, the task is to find a value X such that maximum number of array elements can be expressed in the form (X + p*K). Note: If there are multiple possible values of X, print the minimum among them. Examples: Input: arr[] = {1, 3, 5, 2, 4, 6}, k = 2Output: 1Explanation
11 min read
Find element that maximizes LCM of an Array in the range 1 to M Given an array arr of size N containing numbers in the range [1, M], the task is to find an element, in the range [1, M], which maximises the LCM.Examples: Input: arr[]={3, 4, 2, 7}, M = 8 Output: 5 Explanation: The LCM of existing array (3, 4, 2, 7) = 84 Adding the remaining numbers in 1 to 8 and c
11 min read