Count arrays of length K whose product of elements is same as that of given array

Given an integer array arr[] of length N and an integer K, the task is to count the number of possible arrays of length K such that the product of all elements of that array is equal to the product of all elements of the given array arr[]. Since the answer can be very large, return the answer modulo 109 + 7.

Examples:

Input: arr[] = {2, 3}, K = 3
Output: 9
The product of the elements of the array is 2 * 3 = 6.
And there are 9 such arrays of length 3 possible, product of whose
elements is 6,
{1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2}, {3, 2, 1},
{1, 1, 6}, {1, 6, 1} and {6, 1, 1}.

Input: arr[] = {1, 3, 5, 2}, K = 3
Output: 27

Prerequisites: Prime Factorization, Compute nCr % p
Approach: Let the product of all the elements of arr[] be X. X can be represented by it’s prime factorization, i.e., X = p1c1*p2c2*…*prcr where pi are primes and ci are some non-negative coefficients. Let the K sized array be B[]. Instead of finding actual integers for B[], find the prime factorization for each Bi. The prime factorization of any number from B[] can’t have any prime except the primes which are factor of X because X % Bi should be equal to zero.

Thus, Bi = p1c1i * p2c2i * … * prcri with cij >= 0.
And so, B1 * B2 * … Bk = p1(c11 + c12 + … + c1k) * p2(c21 + c22 + … + c2k) * … * pr(cr1 + cr2 + … + crk).

Equating B1 * B2 * … Bk = X = p1c1*p2c2*…*prcr, we get r equations.
c11 + c12 + … + c1k = c1
c21 + c22 + … + c2k = c2
.
.
.
cr1 + cr2 + … + crk = cr

where cij >= 0

Answer to ith equation is equal to the number of ways of distributing ci identical balls in K distinguishable boxes and so it is ci + K – 1 C K – 1. All the equations are independent, and so final answer = multiplication of answer to each equation.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN (ll)(1e5 + 1)
#define mod (ll)(1e9 + 7)
  
// To store the smallest prime factor
// for every number
ll spf[MAXN];
  
// Initialize map to store
// count of prime factors
map<ll, ll> cnt;
  
// Function to calculate SPF(Smallest Prime Factor)
// for every number till MAXN
void sieve()
{
    spf[1] = 1;
    for (int i = 2; i < MAXN; i++)
  
        // Marking smallest prime factor for every
        // number to be itself
        spf[i] = i;
  
    // Separately marking spf for every even
    // number as 2
    for (int i = 4; i < MAXN; i += 2)
        spf[i] = 2;
  
    for (int i = 3; i * i < MAXN; i++) {
  
        // Checking if i is prime
        if (spf[i] == i) {
  
            // Marking SPF for all numbers divisible by i
            for (int j = i * i; j < MAXN; j += i)
  
                // Marking spf[j] if it is not
                // previously marked
                if (spf[j] == j)
                    spf[j] = i;
        }
    }
}
  
// Function to factorize using spf
// and store in cnt
void factorize(ll f)
{
    while (f > 1) {
        ll x = spf[f];
        while (f % x == 0) {
            cnt[x]++;
            f /= x;
        }
    }
}
  
// Function to return n! % p
ll factorial(ll n, ll p)
{
  
    // Initialize result
    ll res = 1;
    for (int i = 2; i <= n; i++)
        res = (res * i) % p;
    return res;
}
  
// Iterative Function to calculate (x^y)%p
// in O(log y)
ll power(ll x, ll y, ll p)
{
  
    // Initialize result
    ll res = 1;
  
    // Update x if it is >= p
    x = x % p;
  
    while (y > 0) {
  
        // If y is odd, multiply x with result
        if (y & 1)
            res = (res * x) % p;
  
        // y must be even now
        // y = y/2
        y = y >> 1;
        x = (x * x) % p;
    }
    return res;
}
  
// Function that returns n^(-1) mod p
ll modInverse(ll n, ll p)
{
    return power(n, p - 2, p);
}
  
// Function that returns nCr % p
// using Fermat's little theorem
ll nCrModP(ll n, ll r, ll p)
{
    // Base case
    if (r == 0)
        return 1;
  
    // Fill factorial array so that we
    // can find all factorial of r, n
    // and n - r
    ll fac[n + 1];
    fac[0] = 1;
    for (int i = 1; i <= n; i++)
        fac[i] = fac[i - 1] * i % p;
  
    return (fac[n] * modInverse(fac[r], p) % p
            * modInverse(fac[n - r], p) % p)
           % p;
}
  
// Function to return the count the number of possible
// arrays mod P of length K such that the product of all
// elements of that array is equal to the product of
// all elements of the given array of length N
ll countArrays(ll arr[], ll N, ll K, ll P)
{
    // Initialize result
    ll res = 1;
  
    // Call sieve to get spf
    sieve();
  
    for (int i = 0; i < N; i++) {
  
        // Factorize arr[i], count and
        // store its factors in cnt
        factorize(arr[i]);
    }
  
    for (auto i : cnt) {
        int ci = i.second;
        res = (res * nCrModP(ci + K - 1, K - 1, P)) % P;
    }
  
    return res;
}
  
// Driver code
int main()
{
    ll arr[] = { 1, 3, 5, 2 }, K = 3;
    ll N = sizeof(arr) / sizeof(arr[0]);
  
    cout << countArrays(arr, N, K, mod);
  
    return 0;
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 implementation of the approach
  
from math import sqrt
MAXN = 100001
mod = 1000000007
  
# To store the smallest prime factor
# for every number
spf = [0 for i in range(MAXN)]
  
# Initialize map to store
# count of prime factors
cnt = {i:0 for i in range(10)}
  
# Function to calculate SPF(Smallest Prime Factor)
# for every number till MAXN
def sieve():
    spf[1] = 1
    for i in range(2,MAXN):
          
        # Marking smallest prime factor for every
        # number to be itself
        spf[i] = i
  
    # Separately marking spf for every even
    # number as 2
    for i in range(4,MAXN,2):
        spf[i] = 2
  
    for i in range(3,int(sqrt(MAXN))+1,1):
          
        # Checking if i is prime
        if (spf[i] == i):
              
            # Marking SPF for all numbers divisible by i
            for j in range(i * i,MAXN,i):
                  
                # Marking spf[j] if it is not
                # previously marked
                if (spf[j] == j):
                    spf[j] = i
  
# Function to factorize using spf
# and store in cnt
def factorize(f):
    while (f > 1):
        x = spf[f]
        while (f % x == 0):
            cnt[x] += 1
            f = int(f/x)
  
# Function to return n! % p
def factorial(n,p):
      
    #Initialize result
    res = 1
    for i in range(2,n+1,1):
        res = (res * i) % p
    return res
  
# Iterative Function to calculate (x^y)%p
# in O(log y)
def power(x, y, p):
      
    # Initialize result
    res = 1
  
    # Update x if it is >= p
    x = x % p
  
    while (y > 0):
          
        # If y is odd, multiply x with result
        if (y & 1):
            res = (res * x) % p
              
        # y must be even now
        # y = y/2
        y = y >> 1
        x = (x * x) % p
    return res
  
# Function that returns n^(-1) mod p
def modInverse(n,p):
    return power(n, p - 2, p)
  
# Function that returns nCr % p
# using Fermat's little theorem
def nCrModP(n,r,p):
      
    # Base case
    if (r == 0):
        return 1
  
    # Fill factorial array so that we
    # can find all factorial of r, n
    # and n - r
    fac = [0 for i in range(n+1)]
    fac[0] = 1
    for i in range(1,n+1,1):
        fac[i] = fac[i - 1] * i % p
  
    return (fac[n] * modInverse(fac[r], p) % p *
                modInverse(fac[n - r], p) % p)% p
  
# Function to return the count the number of possible
# arrays mod P of length K such that the product of all
# elements of that array is equal to the product of
# all elements of the given array of length N
def countArrays(arr,N,K,P):
    # Initialize result
    res = 1
  
    # Call sieve to get spf
    sieve()
  
    for i in range(N):
        # Factorize arr[i], count and
        # store its factors in cnt
        factorize(arr[i])
  
    for key,value in cnt.items():
        ci = value
        res = (res * nCrModP(ci + K - 1, K - 1, P)) % P
  
    return res
  
# Driver code
if __name__ == '__main__':
    arr = [1, 3, 5, 2]
    K = 3
    N = len(arr)
  
    print(countArrays(arr, N, K, mod))
  
# This code is contributed by
# Surendra_Gangwar

chevron_right


Output:

27


My Personal Notes arrow_drop_up

Coder Machine Learner Social Activist Vocalist

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : SURENDRA_GANGWAR