Skip to content
Related Articles

Related Articles

Improve Article

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

  • Last Updated : 10 Sep, 2021

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 [/Tex] 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;
}

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)
Output:
13

Time Complexity:  O(MAX * $\sqrt{MAX}$) , where  $MAX is the maximum element in the array.




My Personal Notes arrow_drop_up
Recommended Articles
Page :