Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1808. Maximize Number of Nice Divisors - Leetcode Solution

Problem Description

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.

Thought Process

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.

Solution Approach

  • Step 1: Integer Break Insight
    • To maximize the product of exponents that sum to primeFactors, break primeFactors into as many 3's as possible.
    • If the remainder is 1, replace one 3 and the 1 with two 2's (since 2×2 > 3×1).
    • If the remainder is 2, just multiply by 2 at the end.
  • Step 2: Fast Exponentiation
    • Since the answer can be very large, and we need to compute powers efficiently, use fast modular exponentiation.
  • Step 3: Implementation
    • Handle small cases directly (if primeFactors <= 3, return primeFactors).
    • Otherwise, calculate the number of times you can use 3, and handle the remainder appropriately.

Example Walkthrough

Suppose primeFactors = 8:

  • Divide 8 by 3: 8 // 3 = 2, remainder = 2.
  • This means: use two 3's and one 2 (since 3 + 3 + 2 = 8).
  • The maximum product is 3 × 3 × 2 = 18.
  • So, the answer is 18.

If primeFactors = 10:

  • 10 // 3 = 3, remainder = 1.
  • Since remainder is 1, it's better to use two 2's instead of one 3 and one 1.
  • So, use two 3's and two 2's: 3 + 3 + 2 + 2 = 10.
  • Product: 3 × 3 × 2 × 2 = 36.

Time and Space Complexity

  • Brute-force approach:
    • Would involve generating all possible integer partitions of primeFactors, which is exponential in time and infeasible for large inputs.
    • Space complexity would also be exponential due to the storage of partitions.
  • Optimized approach:
    • Time complexity: O(\log primeFactors) due to fast modular exponentiation.
    • Space complexity: O(1), as only a few variables are used.

Summary

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.

Code Implementation

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;
    }
};