最近有点水逆,希望厄运赶快退散,一会会去祈福的。
这场周赛依旧是3题遗憾离场,第4题经过提示其实涉及的算法都会但是实在是emmmm过于综合。
7023. 操作使得分最大
提示
困难
10
相关企业
给你一个长度为 n
的正整数数组 nums
和一个整数 k
。
一开始,你的分数为 1
。你可以进行以下操作至多 k
次,目标是使你的分数最大:
- 选择一个之前没有选过的 非空 子数组
nums[l, ..., r]
。 - 从
nums[l, ..., r]
里面选择一个 质数分数 最高的元素x
。如果多个元素质数分数相同且最高,选择下标最小的一个。 - 将你的分数乘以
x
。
nums[l, ..., r]
表示 nums
中起始下标为 l
,结束下标为 r
的子数组,两个端点都包含。
一个整数的 质数分数 等于 x
不同质因子的数目。比方说, 300
的质数分数为 3
,因为 300 = 2 * 2 * 3 * 5 * 5
。
请你返回进行至多 k
次操作后,可以得到的 最大分数 。
由于答案可能很大,请你将结果对 109 + 7
取余后返回。
示例 1:
输入:nums = [8,3,9,3,8], k = 2
输出:81
解释:进行以下操作可以得到分数 81 :
- 选择子数组 nums[2, ..., 2] 。nums[2] 是子数组中唯一的元素。所以我们将分数乘以 nums[2] ,分数变为 1 * 9 = 9 。
- 选择子数组 nums[2, ..., 3] 。nums[2] 和 nums[3] 质数分数都为 1 ,但是 nums[2] 下标更小。所以我们将分数乘以 nums[2] ,分数变为 9 * 9 = 81 。
81 是可以得到的最高得分。
示例 2:
输入:nums = [19,12,14,6,10,18], k = 3
输出:4788
解释:进行以下操作可以得到分数 4788 :
- 选择子数组 nums[0, ..., 0] 。nums[0] 是子数组中唯一的元素。所以我们将分数乘以 nums[0] ,分数变为 1 * 19 = 19 。
- 选择子数组 nums[5, ..., 5] 。nums[5] 是子数组中唯一的元素。所以我们将分数乘以 nums[5] ,分数变为 19 * 18 = 342 。
- 选择子数组 nums[2, ..., 3] 。nums[2] 和 nums[3] 质数分数都为 2,但是 nums[2] 下标更小。所以我们将分数乘以 nums[2] ,分数变为 342 * 14 = 4788 。
4788 是可以得到的最高的分。
提示:
1 <= nums.length == n <= 105
1 <= nums[i] <= 105
1 <= k <= min(n * (n + 1) / 2, 109)
Solution
class Solution:
def maximumScore(self, nums: List[int], k: int) -> int:
# 计算质因数个数
def cal_pri(n):
s = set() # 存储所有质因数的哈希表
x = n
i = 2
while i*i <= x:
while x%i == 0:
s.add(i)
x //= i
i += 1
if x > 1:
s.add(x)
return len(s)
# 快速幂
def fast_pow(x, e):
res = 1
while e:
if e % 2:
res *= x
res %= mod
x = x ** 2 % mod
e //= 2
return res
arr = [cal_pri(num) for num in nums]
# 907.子数组的最小值之和 - 的板子
# 单调栈
n = len(arr)
monoStack = []
left = [0] * n
right = [0] * n
for i, x in enumerate(arr):
while monoStack and x > arr[monoStack[-1]]:
monoStack.pop()
left[i] = i - (monoStack[-1] if monoStack else -1)
monoStack.append(i)
monoStack = []
for i in range(n - 1, -1, -1):
while monoStack and arr[i] >= arr[monoStack[-1]]:
monoStack.pop()
right[i] = (monoStack[-1] if monoStack else n) - i
monoStack.append(i)
ans = 1
# 处理个数
mod = 1000000007
for x, l, r in sorted(zip(nums, left, right))[::-1]:
if k >= r * l:
ans *= fast_pow(x, l * r)
ans %= mod
k -= r * l
else:
ans *= fast_pow(x, k)
ans %= mod
k = 0
if k == 0:
break
return ans
另外对于这种批量质因数可以集中处理:
MOD = 10 ** 9 + 7
MX = 10 ** 5 + 1
omega = [0] * MX
for i in range(2, MX): # 预处理 omega
if omega[i] == 0: # i 是质数
for j in range(i, MX, i):
omega[j] += 1 # i 是 j 的一个质因子
作者:灵茶山艾府
链接:https://leetcode.cn/problems/apply-operations-to-maximize-score/solutions/2385936/gong-xian-fa-dan-diao-zhan-pythonjavacgo-23c4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
以上。
标签:分数,周赛,nums,质数,数组,monoStack,质因数,...,358 From: https://blog.51cto.com/u_15763108/7068856