📅  最后修改于: 2023-12-03 15:22:34.464000             🧑  作者: Mango
在这个问题中,我们需要计算给定整数数组中,乘积不含重复素因子的子数组个数。
暴力方法是对于每个子数组,计算它的乘积并判断其是否含有重复素因子。这个方法需要 $O(n^2)$ 的时间复杂度,无法通过本题目。
我们可以使用类似滑动窗口的方法。假设当前考虑的子数组为 $[l, r]$,我们记 $P_l$ 为 $[l, r]$ 中所有数的乘积,若 $P_l$ 不含重复素因子,则 $[l, r]$ 一定是符合条件的子数组,我们可以令计数器 $ans$ 加一。
若 $P_l$ 含有重复素因子,则应该尝试让它变成不含重复素因子的乘积。设当前考虑到 $P_r$,我们尝试将 $l$ 不断右移,同时将 $P_l$ 除以 $a_l$,直到 $P_l$ 除以 $a_l$ 后不再含有重复素因子为止。需要使用哈希表记录每个素因子是否出现过。
使用哈希表有一个问题,那就是确定哈希表的 key 以及哈希函数。我们可以将素因子看作 key,将其对应出现的位置作为 value。在滑动窗口移动的过程中,我们可以非常简单地更新哈希表。
因为所有的素因子的值都比较小,我们可以暴力枚举素因子,选取它们为 key,时间复杂度为 $O(n \sqrt{m})$,其中 $m$ 表示所有元素的乘积。
完整算法的时间复杂度为 $O(n \sqrt{m})$,空间复杂度为 $O(\sqrt{m})$。
def countSubarrays(nums: List[int]) -> int:
def calc_pfactors(x):
ret = set()
for i in range(2, int(x**0.5) + 1):
if x % i == 0:
ret.add(i)
while x % i == 0:
x //= i
if x > 1:
ret.add(x)
return list(ret)
ans = 0
l, r = 0, 0
pfactors = {}
while r < len(nums):
cur_pfactors = calc_pfactors(nums[r])
for p in cur_pfactors:
if p in pfactors:
while pfactors[p] >= l:
pfactors[nums[l]] -= 1
if pfactors[nums[l]] == 0:
pfactors.pop(nums[l])
l += 1
pfactors.update({p: r for p in cur_pfactors})
ans += r - l + 1
r += 1
return ans
该算法使用 Python 语言实现。其中,calc_pfactors
函数返回 $x$ 的素因子列表。在滑动窗口移动的过程中,哈希表 pfactors
记录每个素因子最后出现的位置。若当前的乘积中含有重复素因子,则将窗口左端点右移。最后,答案即为符合条件的子数组个数。