📜  计算具有 GCD 且 N 等于数字本身的数字(1)

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

计算具有 GCD 且 N 等于数字本身的数字

在数学中,GCD(最大公约数)是两个或多个整数的最大公因数。本题要求我们计算具有GCD且N等于数字本身的数字。

解法

我们可以从最简单的做法开始,逐步优化。首先,我们可以枚举所有的数字 $N$,然后对每个数字 $N$ 以及 $[1, N-1]$ 中的数字进行 GCD 计算,如果与 $N$ 的 GCD 为 $1$,那么这个数字就符合条件。

def is_gcd_n(x: int) -> bool:
    for i in range(1, x):
        if math.gcd(i, x) == 1:
            return False
    return True

def find_gcd_n_list(n: int) -> List[int]:
    res = []
    for i in range(2, n+1):
        if is_gcd_n(i):
            res.append(i)
    return res

这个做法的时间复杂度为 $O(N^2 \log N)$,对于较大的 $N$,可能会超时。接下来,我们可以优化一下枚举的范围,由于 $N$ 除了 $1$ 以外没有其他的因数,那么符合条件的数字一定是因数不超过 $\sqrt{N}$ 的数字,所以我们可以只枚举到 $\sqrt{N}$,这样的时间复杂度为 $O(N \sqrt{N} \log N)$。

def find_gcd_n_list(n: int) -> List[int]:
    res = []
    for i in range(2, n+1):
        bound = int(math.sqrt(i))+1
        flag = True
        for j in range(2, bound):
            if i % j == 0 and math.gcd(j, i) == 1:
                flag = False
                break
        if flag:
            res.append(i)
    return res

我们还可以再次优化,注意到一个数与一个质数的 GCD 要么是 $1$ 要么是该质数,因此我们只需要枚举质数,然后计算其幂次,再将不超过 $N$ 的数字加入结果集中即可。这样的时间复杂度为 $O(\sqrt{N} \log N)$。

def find_gcd_n_list(n: int) -> List[int]:
    res = []
    bound = int(math.sqrt(n))+1
    for i in range(2, bound):
        if is_prime(i):
            j = i
            while j <= n:
                res.append(j)
                j *= i
    return res

def is_prime(x: int) -> bool:
    if x < 2:
        return False
    for i in range(2, int(x ** 0.5) + 1):
        if x % i == 0:
            return False
    return True
总结

本题我们一开始从暴力开始,逐步优化算法,开发者们一定要注意这种自底向上的思路。同时,优化算法不仅要注重时间复杂度,还要注重空间复杂度,开发者们应该对常用的算法和数据结构有一定掌握,这样才能设计出时间和空间都优秀的算法。