2818. Apply-Operations-To-Maximize-Score

Question Link

Difficulty: Hard

I have no clue how to do this question lmao

ass Solution(object):
    MOD = int(1e9 + 7)
    def maximumScore(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        n = len(nums)
        prime_scores = [0] * n

        max_element = max(nums)
        primes = self.get_primes(max_element)

        for index in range(n):
            num = nums[index]

            for prime in primes:
                if prime * prime > num:
                    break
                if num % prime != 0:
                    continue
                
                prime_scores[index] += 1
                while num % prime == 0:
                    num //= prime

            if num > 1:
                prime_scores[index] += 1
        
        next_dominant = [n] * n
        prev_dominant = [-1] * n
        decreasing_prime_score_stack = deque()

        for index in range(n):
            while (
                decreasing_prime_score_stack
                and prime_scores[decreasing_prime_score_stack[-1]]
                < prime_scores[index]
            ):
                top_index = decreasing_prime_score_stack.pop()
                next_dominant[top_index] = index

            if decreasing_prime_score_stack:
                prev_dominant[index] = decreasing_prime_score_stack[-1]

            decreasing_prime_score_stack.append(index)

        num_of_subarrays = [
            (next_dominant[i] - i) * (i - prev_dominant[i]) for i in range(n)
        ]

        sorted_array = sorted(enumerate(nums), key=lambda x: -x[1]) 
        score = 1

        def _power(base, exponent):
            res = 1
            while exponent > 0:
                if exponent % 2:
                    res = (res * base) % self.MOD
                base = (base * base) % self.MOD
                exponent //= 2

            return res
        
        processing_index = 0

        while k > 0:
            index, num = sorted_array[processing_index]
            processing_index += 1
            operations = min(k, num_of_subarrays[index])
            score = (score * _power(num, operations)) % self.MOD
            k -= operations
        
        return score

    def get_primes(self, limit):
        is_prime = [True] * (limit + 1)
        primes = []

        for number in range(2, limit + 1):
            if not is_prime[number]:
                continue
            
            primes.append(number)
            for multiple in range(number * number, limit + 1, number):
                is_prime[multiple] = False
        
        return primes

Time Complexity: O(n (log m + log n) + m log log m)

Space Complexity: O(max(n, m))