📜  更改数组以使最大元素为数组的LCM的方法数量

📅  最后修改于: 2021-04-17 12:59:56             🧑  作者: Mango

给定数组arr [] ,任务是对唯一数组的数量进行计数,方法是将给定数组的元素更新为[1,arr [i]]范围内的任何元素,以使更新后的数组等于最大元素。

例子:

方法:

  • 为了使最大元素成为数组的LCM,我们需要修复数组的最大元素。
  • 因为,我们已经确定了一些数字 i 最大,现在对于LCM  i ,我们需要确保数组中的每个元素都是的倍数 i 包括 i
  • 我们会找到影响数字的因素 i 并找到将它们放置在数组中的方法数量。
  • 比方说,  i  x, y, z 。因素的数量是 3
  • 让我们假设 x  a 意味着有 a 数组中具有大于等于的位置数 x 然后让 y  b 职位和 z  c 职位。
  • 现在,有几种方式分配x [/ Tex]  a 职位,  y  b - a 职位和 z  c - b - a 职位是 3 ^ a * 2 ^ {(b - a)} * 1 ^ {(c - b - a)} 等等。
  • 现在,我们必须减去具有LCM的那些方法 i  i 不在这里。
  • 我们需要精简 2 ^ b * 1 ^ {(c - b)} 从方式上
  • 我们将使用BIT(二叉索引树)来查找数量大于某个数量的头寸 x

下面是上述方法的实现:

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


输出:
13

时间复杂度:  O(MAX * $\sqrt{MAX}$) , 在哪里 $MAX 是数组中的最大元素。