From ed5c176d42875951e1b01fad3959310efc8483f6 Mon Sep 17 00:00:00 2001 From: 0xff-dev Date: Sat, 29 Mar 2025 21:25:37 +0800 Subject: [PATCH] Add solution and test-cases for problem 2818 --- .../README.md | 49 +++++++ .../Solution.go | 138 +++++++++++++++++- .../Solution_test.go | 20 +-- 3 files changed, 196 insertions(+), 11 deletions(-) create mode 100644 leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/README.md diff --git a/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/README.md b/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/README.md new file mode 100644 index 000000000..f6358c04f --- /dev/null +++ b/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/README.md @@ -0,0 +1,49 @@ +# [2818.Apply Operations to Maximize Score][title] + +## Description + +You are given an array `nums` of `n` positive integers and an integer `k`. + +Initially, you start with a score of `1`. You have to maximize your score by applying the following operation at most `k` times: + +- Choose any **non-empty** subarray `nums[l, ..., r]` that you haven't chosen previously. +- Choose an element `x` of `nums[l, ..., r]` with the highest **prime score**. If multiple such elements exist, choose the one with the smallest index. +- Multiply your score by `x`. + +Here, `nums[l, ..., r]` denotes the subarray of `nums` starting at index `l` and ending at the index `r`, both ends being inclusive. + +The **prime score** of an integer `x` is equal to the number of distinct prime factors of x. For example, the prime score of `300` is `3` since `300 = 2 * 2 * 3 * 5 * 5`. + +Return the **maximum possible score** after applying at most `k` operations. + +Since the answer may be large, return it modulo `10^9 + 7`. + +**Example 1:** + +``` +Input: nums = [8,3,9,3,8], k = 2 +Output: 81 +Explanation: To get a score of 81, we can apply the following operations: +- Choose subarray nums[2, ..., 2]. nums[2] is the only element in this subarray. Hence, we multiply the score by nums[2]. The score becomes 1 * 9 = 9. +- Choose subarray nums[2, ..., 3]. Both nums[2] and nums[3] have a prime score of 1, but nums[2] has the smaller index. Hence, we multiply the score by nums[2]. The score becomes 9 * 9 = 81. +It can be proven that 81 is the highest score one can obtain. +``` + +**Example 2:** + +``` +Input: nums = [19,12,14,6,10,18], k = 3 +Output: 4788 +Explanation: To get a score of 4788, we can apply the following operations: +- Choose subarray nums[0, ..., 0]. nums[0] is the only element in this subarray. Hence, we multiply the score by nums[0]. The score becomes 1 * 19 = 19. +- Choose subarray nums[5, ..., 5]. nums[5] is the only element in this subarray. Hence, we multiply the score by nums[5]. The score becomes 19 * 18 = 342. +- Choose subarray nums[2, ..., 3]. Both nums[2] and nums[3] have a prime score of 2, but nums[2] has the smaller index. Hence, we multipy the score by nums[2]. The score becomes 342 * 14 = 4788. +It can be proven that 4788 is the highest score one can obtain. +``` + +## 结语 + +如果你同我一样热爱数据结构、算法、LeetCode,可以关注我 GitHub 上的 LeetCode 题解:[awesome-golang-algorithm][me] + +[title]: https://leetcode.com/problems/apply-operations-to-maximize-score/ +[me]: https://github.com/kylesliu/awesome-golang-algorithm diff --git a/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution.go b/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution.go index d115ccf5e..e7b7148e5 100755 --- a/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution.go +++ b/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution.go @@ -1,5 +1,141 @@ package Solution -func Solution(x bool) bool { +import ( + "container/heap" +) + +const mod2818 = 1_000_000_007 + +type Pair2818 struct { + value int + index int +} + +// PriorityQueue implements a priority queue for pairs based on value +type PriorityQueue []Pair2818 + +func (pq PriorityQueue) Len() int { + return len(pq) +} + +func (pq PriorityQueue) Less(i, j int) bool { + return pq[i].value > pq[j].value // Max-heap based on value +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] +} + +func (pq *PriorityQueue) Push(x interface{}) { + *pq = append(*pq, x.(Pair2818)) +} + +func (pq *PriorityQueue) Pop() interface{} { + old := *pq + n := len(old) + x := old[n-1] + *pq = old[0 : n-1] return x } + +// Helper function to compute the number of distinct prime factors +func distinctPrimeFactors(x int) int { + count := 0 + for i := 2; i*i <= x; i++ { + if x%i == 0 { + count++ + for x%i == 0 { + x /= i + } + } + } + if x > 1 { + count++ // If x is a prime number larger than sqrt(original x) + } + return count +} + +func Solution(nums []int, k int) int { + n := len(nums) + primeScores := make([]int, n) + + for i := 0; i < n; i++ { + primeScores[i] = distinctPrimeFactors(nums[i]) + } + + nextDominant := make([]int, n) + prevDominant := make([]int, n) + for i := 0; i < n; i++ { + nextDominant[i] = n + prevDominant[i] = -1 + } + + stack := []int{} + + for i := 0; i < n; i++ { + for len(stack) > 0 && primeScores[stack[len(stack)-1]] < primeScores[i] { + topIndex := stack[len(stack)-1] + stack = stack[:len(stack)-1] + nextDominant[topIndex] = i + } + + if len(stack) > 0 { + prevDominant[i] = stack[len(stack)-1] + } + + stack = append(stack, i) + } + + numOfSubarrays := make([]int64, n) + for i := 0; i < n; i++ { + numOfSubarrays[i] = int64(nextDominant[i]-i) * int64(i-prevDominant[i]) + } + + pq := &PriorityQueue{} + heap.Init(pq) + + // Push each number and its index onto the priority queue + for i := 0; i < n; i++ { + heap.Push(pq, Pair2818{value: nums[i], index: i}) + } + + score := int64(1) + + // Process elements while there are operations left + for k > 0 { + // Get the element with the maximum value from the queue + top := heap.Pop(pq).(Pair2818) + num := top.value + index := top.index + + // Calculate operations to apply on the current element + operations := int64(k) + if operations > numOfSubarrays[index] { + operations = numOfSubarrays[index] + } + + // Update the score + score = (score * power(num, operations)) % mod2818 + + // Reduce the remaining operations count + k -= int(operations) + } + + return int(score) +} + +// Helper function to compute the power of a number modulo mod2818 +func power(base int, exponent int64) int64 { + res := int64(1) + + // Calculate the exponentiation using binary exponentiation + for exponent > 0 { + if exponent%2 == 1 { + res = (res * int64(base)) % mod2818 + } + base = (base * base) % mod2818 + exponent /= 2 + } + + return res +} diff --git a/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution_test.go b/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution_test.go index 14ff50eb4..fe1e36b28 100755 --- a/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution_test.go +++ b/leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution_test.go @@ -10,30 +10,30 @@ func TestSolution(t *testing.T) { // 测试用例 cases := []struct { name string - inputs bool - expect bool + nums []int + k int + expect int }{ - {"TestCase", true, true}, - {"TestCase", true, true}, - {"TestCase", false, false}, + {"TestCase1", []int{8, 3, 9, 3, 8}, 2, 81}, + {"TestCase2", []int{19, 12, 14, 6, 10, 18}, 3, 4788}, } // 开始测试 for i, c := range cases { t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) { - got := Solution(c.inputs) + got := Solution(c.nums, c.k) if !reflect.DeepEqual(got, c.expect) { - t.Fatalf("expected: %v, but got: %v, with inputs: %v", - c.expect, got, c.inputs) + t.Fatalf("expected: %v, but got: %v, with inputs: %v %v", + c.expect, got, c.nums, c.k) } }) } } -// 压力测试 +// 压力测试 func BenchmarkSolution(b *testing.B) { } -// 使用案列 +// 使用案列 func ExampleSolution() { }