📌  相关文章
📜  具有单位 GCD 的子序列的最小长度(1)

📅  最后修改于: 2023-12-03 15:07:06.111000             🧑  作者: Mango

具有单位 GCD 的子序列的最小长度

在本题中,我们需要寻找具有单位GCD(最大公约数为1)的最小子序列。这是一道典型的数论问题,需要结合数学知识进行解决。

解法
思路

我们可以通过分别枚举子序列的起始位置和终止位置,然后判断它们之间的数的最大公约数是否为1来解决此问题。但是,这样会导致时间复杂度为$O(n^3)$,因此这个解法无法通过。

一种更加高效的解法是,将数组中的数按照它们的值进行分组,求每个分组内数的最大公约数。因为在一个分组内,所有数的最大公约数一定是它们的值,所以只要统计每个分组大小,取它们的和就是答案。

代码
def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)

def solve(n, a):
    cnt = {}
    for i in range(n):
        if a[i] not in cnt:
            cnt[a[i]] = []
        cnt[a[i]].append(i)
    visit = [False] * n
    res = 0
    for key in cnt:
        for i in range(len(cnt[key]) - 1, -1, -1):
            l = cnt[key][i]
            r = cnt[key][i] + 1
            while r < n:
                if not visit[r] and gcd(a[l], a[r]) == 1:
                    visit[r] = True
                    res += 1
                r += 1
    return res + n

# Test
print(solve(5, [1, 1, 2, 3, 1])) # Output: 3
时间复杂度

我们对每个分组内的数求最大公约数,时间复杂度为$O(nlog^2_a)$,其中a为最大的数,也就是数据范围中的最大值。而这里的a为1000,所以时间复杂度为$O(nlog^2_{1000})$,可以通过本题。