Open In App

Number of ways to change the Array such that largest element is LCM of array

Improve
Improve
Like Article
Like
Save
Share
Report

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);

                    

Output
13








Time Complexity:

 O(MAX * $\sqrt{MAX}$)

, where

 $MAX

is the maximum element in the array.



Last Updated : 06 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads