You are given two integers: n
and k
. Your task is to count the number of different arrays of length n
such that the product of all the elements in the array is exactly k
. Each element in the array must be a positive integer (greater than 0). The answer should be returned modulo 10^9 + 7
.
Constraints:
At first glance, one might try to generate all possible arrays of length n
, check their product, and count those that equal k
. However, this quickly becomes unfeasible as the number of possible arrays grows exponentially with n
and k
. We need a more efficient way to count the arrays without generating them.
The key realization is that the product of the array elements must be exactly k
. Since elements are positive integers, we can think in terms of the prime factorization of k
. Each element in the array will contribute some of these prime factors. The problem reduces to distributing the prime factors of k
among n
slots (array elements).
This is a classic combinatorics problem, where we count the number of non-negative integer solutions to a sum, which can be solved with the "stars and bars" method.
Let's break down the solution step-by-step:
k
:
k
as a product of its prime factors: k = p1^a1 * p2^a2 * ... * pm^am
.pi
with exponent ai
, we need to distribute ai
indistinguishable objects (prime factors) into n
distinguishable bins (array elements).C(ai + n - 1, n - 1)
, where C
is the binomial coefficient.10^9 + 7
.n + max exponent
for efficient binomial coefficient calculation.By using combinatorics and prime factorization, we avoid brute-force enumeration and achieve an efficient solution.
Let's consider n = 3
and k = 6
.
6 = 2^1 * 3^1
.C(1 + 3 - 1, 3 - 1) = C(3, 2) = 3
.
C(3, 2) = 3
.
3 * 3 = 9
.
The valid arrays (with their products) are:
n
with elements from 1 to k
.O(k^n)
(infeasible for large n
).k
: O(√k)
.O(n + max exponent)
for precomputing factorials, and O(number of prime factors)
for the product.O(√k + n + log k)
(since the number of primes is at most log k
).O(n + max exponent)
for factorials.
The problem of counting arrays with a given product is elegantly solved by recognizing it as a combinatorial distribution of prime factors. By prime factorizing k
and using the stars and bars method for each exponent, we efficiently count the number of valid arrays. Precomputing factorials allows for fast binomial coefficient calculation, making the solution both efficient and scalable.
MOD = 10**9 + 7
def prime_factors(k):
factors = {}
d = 2
while d * d <= k:
count = 0
while k % d == 0:
k //= d
count += 1
if count:
factors[d] = count
d += 1
if k > 1:
factors[k] = 1
return factors
def precompute_factorials(limit):
fact = [1] * (limit + 1)
inv = [1] * (limit + 1)
for i in range(1, limit + 1):
fact[i] = fact[i-1] * i % MOD
inv[limit] = pow(fact[limit], MOD-2, MOD)
for i in range(limit-1, -1, -1):
inv[i] = inv[i+1] * (i+1) % MOD
return fact, inv
def comb(n, k, fact, inv):
if k < 0 or k > n:
return 0
return fact[n] * inv[k] % MOD * inv[n-k] % MOD
def waysToFillArray(queries):
res = []
max_n = max(n for n, k in queries)
max_k = max(k for n, k in queries)
# Maximum possible exponent is log2(max_k) * max_n
fact, inv = precompute_factorials(100 + 14 * 100)
for n, k in queries:
factors = prime_factors(k)
ans = 1
for p, exp in factors.items():
ans = ans * comb(exp + n - 1, n - 1, fact, inv) % MOD
res.append(ans)
return res
# Example usage:
# queries = [(3, 6)]
# print(waysToFillArray(queries)) # Output: [9]
#include <vector>
#include <unordered_map>
using namespace std;
const int MOD = 1e9 + 7;
const int MAX = 2000;
vector<long long> fact(MAX+1, 1), inv(MAX+1, 1);
long long mod_pow(long long x, long long y, int mod) {
long long res = 1;
while (y) {
if (y & 1) res = res * x % mod;
x = x * x % mod;
y >>= 1;
}
return res;
}
void precompute() {
for (int i = 1; i <= MAX; ++i)
fact[i] = fact[i-1] * i % MOD;
inv[MAX] = mod_pow(fact[MAX], MOD-2, MOD);
for (int i = MAX-1; i >= 0; --i)
inv[i] = inv[i+1] * (i+1) % MOD;
}
long long comb(int n, int k) {
if (k < 0 || k > n) return 0;
return fact[n] * inv[k] % MOD * inv[n-k] % MOD;
}
unordered_map<int, int> prime_factors(int k) {
unordered_map<int, int> factors;
for (int d = 2; d * d <= k; ++d) {
while (k % d == 0) {
factors[d]++;
k /= d;
}
}
if (k > 1) factors[k]++;
return factors;
}
vector<int> waysToFillArray(vector<pair<int, int>>& queries) {
precompute();
vector<int> res;
for (auto& q : queries) {
int n = q.first, k = q.second;
auto factors = prime_factors(k);
long long ans = 1;
for (auto& f : factors) {
int exp = f.second;
ans = ans * comb(exp + n - 1, n - 1) % MOD;
}
res.push_back(ans);
}
return res;
}
// Example usage:
// vector<pair<int, int>> queries = {{3, 6}};
// auto result = waysToFillArray(queries); // result[0] == 9
import java.util.*;
public class Solution {
static final int MOD = 1000000007;
static final int MAX = 2000;
static long[] fact = new long[MAX+1];
static long[] inv = new long[MAX+1];
static {
fact[0] = 1;
for (int i = 1; i <= MAX; i++) fact[i] = fact[i-1] * i % MOD;
inv[MAX] = pow(fact[MAX], MOD-2);
for (int i = MAX-1; i >= 0; i--) inv[i] = inv[i+1] * (i+1) % MOD;
}
static long pow(long a, long b) {
long res = 1;
while (b > 0) {
if ((b & 1) == 1) res = res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
static Map<Integer, Integer> primeFactors(int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int d = 2; d * d <= k; d++) {
while (k % d == 0) {
map.put(d, map.getOrDefault(d, 0) + 1);
k /= d;
}
}
if (k > 1) map.put(k, map.getOrDefault(k, 0) + 1);
return map;
}
static long comb(int n, int k) {
if (k < 0 || k > n) return 0;
return fact[n] * inv[k] % MOD * inv[n - k] % MOD;
}
public int[] waysToFillArray(int[][] queries) {
int[] res = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int n = queries[i][0], k = queries[i][1];
Map<Integer, Integer> factors = primeFactors(k);
long ans = 1;
for (int exp : factors.values()) {
ans = ans * comb(exp + n - 1, n - 1) % MOD;
}
res[i] = (int)ans;
}
return res;
}
// Example usage:
// int[][] queries = {{3, 6}};
// System.out.println(Arrays.toString(new Solution().waysToFillArray(queries))); // [9]
}
const MOD = 1e9 + 7;
const MAX = 2000;
function precomputeFactorials(limit) {
const fact = new Array(limit + 1).fill(1);
const inv = new Array(limit + 1).fill(1);
for (let i = 1; i <= limit; i++) {
fact[i] = fact[i-1] * i % MOD;
}
inv[limit] = pow(fact[limit], MOD-2);
for (let i = limit-1; i >= 0; i--) {
inv[i] = inv[i+1] * (i+1) % MOD;
}
return [fact, inv];
}
function pow(a, b) {
let res = 1, base = a % MOD;
while (b > 0) {
if (b & 1) res = res * base % MOD;
base = base * base % MOD;
b >>= 1;
}
return res;
}
function primeFactors(k) {
const map = new Map();
let d = 2;
while (d * d <= k) {
let cnt = 0;
while (k % d === 0) {
cnt++;
k = Math.floor(k / d);
}
if (cnt) map.set(d, cnt);
d++;
}
if (k > 1) map.set(k, 1);
return map;
}
function comb(n, k, fact, inv) {
if (k < 0 || k > n) return 0;
return fact[n] * inv[k] % MOD * inv[n-k] % MOD;
}
function waysToFillArray(queries) {
let maxN = 0, maxK = 0;
for (const [n, k] of queries) {
maxN = Math.max(maxN, n);
maxK = Math.max(maxK, k);
}
const [fact, inv] = precomputeFactorials(MAX);
const res = [];
for (const [n, k] of queries) {
const factors = primeFactors(k);
let ans = 1;
for (const exp of factors.values()) {
ans = ans * comb(exp + n - 1, n - 1, fact, inv) % MOD;
}
res.push(ans);
}
return res;
}
// Example usage:
// console.log(waysToFillArray([[3, 6]])); // [9]