You are given a positive integer primeFactors
. Your task is to maximize the number of "nice divisors" of a positive integer n
that you can construct, given that the total number of prime factors (counted with multiplicity) of n
is at most primeFactors
.
A "nice divisor" of n
is a divisor of n
that is divisible by all the prime factors of n
.
In other words, you are to choose a multiset of prime numbers (with total count at most primeFactors
), and assign exponents to each, such that the product of all exponents equals primeFactors
. Then, maximize the number of nice divisors, which is the product of the exponents.
Since the answer can be very large, return it modulo 10^9 + 7
.
At first glance, the problem seems to ask for a brute-force search: try all possible ways to distribute primeFactors
among potential prime bases, compute the number of nice divisors for each, and take the maximum. However, this is computationally infeasible for large primeFactors
.
On closer inspection, the problem can be reframed as: Given primeFactors
, split it into a sum of positive integers (the exponents), so that the product of these exponents is maximized. This is a classic integer break problem, where the maximum product is achieved by breaking the number into as many 3's as possible, with some adjustments for remainders.
Thus, the key insight is to use mathematical optimization rather than brute-force enumeration.
primeFactors
, break primeFactors
into as many 3's as possible.primeFactors <= 3
, return primeFactors
).
Suppose primeFactors = 8
:
If primeFactors = 10
:
primeFactors
, which is exponential in time and infeasible for large inputs.O(\log primeFactors)
due to fast modular exponentiation.O(1)
, as only a few variables are used.The solution leverages the mathematical principle that breaking a number into as many 3's as possible maximizes the product of its parts. By reducing the problem to modular exponentiation and handling remainders carefully, we achieve an elegant and efficient solution. This approach is both optimal and highly performant compared to brute-force methods.
class Solution:
def maxNiceDivisors(self, primeFactors: int) -> int:
MOD = 10 ** 9 + 7
if primeFactors <= 3:
return primeFactors
def fast_pow(a, b):
res = 1
while b:
if b % 2:
res = res * a % MOD
a = a * a % MOD
b //= 2
return res
q, r = divmod(primeFactors, 3)
if r == 0:
return fast_pow(3, q)
elif r == 1:
return fast_pow(3, q - 1) * 4 % MOD
else: # r == 2
return fast_pow(3, q) * 2 % MOD
class Solution {
public:
int maxNiceDivisors(int primeFactors) {
const int MOD = 1e9 + 7;
if (primeFactors <= 3) return primeFactors;
long long res = 1;
int q = primeFactors / 3, r = primeFactors % 3;
auto fast_pow = [](long long a, int b, int mod) {
long long res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
};
if (r == 0) {
return fast_pow(3, q, MOD);
} else if (r == 1) {
return (fast_pow(3, q - 1, MOD) * 4) % MOD;
} else { // r == 2
return (fast_pow(3, q, MOD) * 2) % MOD;
}
}
};
class Solution {
public int maxNiceDivisors(int primeFactors) {
int MOD = 1000000007;
if (primeFactors <= 3) return primeFactors;
int q = primeFactors / 3, r = primeFactors % 3;
long res;
if (r == 0) {
res = fastPow(3, q, MOD);
} else if (r == 1) {
res = fastPow(3, q - 1, MOD) * 4 % MOD;
} else {
res = fastPow(3, q, MOD) * 2 % MOD;
}
return (int) res;
}
private long fastPow(long a, int b, int mod) {
long res = 1;
while (b > 0) {
if ((b & 1) != 0) {
res = res * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return res;
}
}
var maxNiceDivisors = function(primeFactors) {
const MOD = 1e9 + 7;
if (primeFactors <= 3) return primeFactors;
function fastPow(a, b) {
let res = 1;
while (b > 0) {
if (b % 2 === 1) res = res * a % MOD;
a = a * a % MOD;
b = Math.floor(b / 2);
}
return res;
}
let q = Math.floor(primeFactors / 3);
let r = primeFactors % 3;
if (r === 0) {
return fastPow(3, q);
} else if (r === 1) {
return fastPow(3, q - 1) * 4 % MOD;
} else {
return fastPow(3, q) * 2 % MOD;
}
};