青训营X豆包MarsCode 技术训练营第五课|豆包MarsCode AI 刷题

54 阅读3分钟

小S在学习素数因子的分解,她希望在[1,n][1,n]的范围内,找到一些连续的自然数,这些数的乘积最多包含kk个不同的素因子。你的任务是帮助小S找到可以取的连续自然数的最大长度。

连续的自然数指的是不能重复且相邻数的差为1的一组正整数,例如 [2, 3, 4, 5] 和 [5, 6, 7] 都是连续的取数。 为了解决这个问题,我们需要找到在 [1,n][1,n] 范围内的连续自然数序列,使得这些数的乘积包含的不同的素因子数量不超过 kk,并且序列的长度尽可能长。

算法步骤:

  1. 素因子分解:

    • 对于每个数 ii 从 1 到 nn,进行素因子分解,并记录每个数的素因子集合。
  2. 滑动窗口:

    • 使用滑动窗口的方法来找到连续数的乘积,其包含的不同的素因子数量不超过 kk。
    • 滑动窗口的左端点从 1 开始,右端点从 2 开始。
    • 随着右端点的移动,更新窗口内所有数的乘积的素因子集合。
  3. 更新素因子集合:

    • 当右端点移动到新的数时,将这个数的素因子添加到当前的素因子集合中。
    • 当左端点被排除出窗口时,从素因子集合中移除这个数的素因子。
  4. 检查素因子数量:

    • 在每一步,检查当前窗口内所有数的乘积的素因子集合的大小是否超过 kk。
    • 如果超过 kk,则移动左端点,缩小窗口,直到素因子数量不超过 kk。
  5. 记录最大长度:

    • 在移动右端点的过程中,记录窗口的最大长度。

代码实现:

python
from collections import defaultdict

def prime_factors(n):
    factors = set()
    i = 2
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
            factors.add(i)
    if n > 1:
        factors.add(n)
    return factors

def max_length(n, k):
    max_len = 0
    left = 1
    factors = set()
    
    for right in range(1, n + 1):
        factors.update(prime_factors(right))
        if len(factors) > k:
            while len(factors) > k:
                factors.discard(prime_factors(left).pop())
                left += 1
        max_len = max(max_len, right - left + 1)
    
    return max_len

# 示例
n = 10
k = 2
print(max_length(n, k))  # 输出: 4

解释:

  • 函数 prime_factors 用于计算一个数的素因子集合。
  • 函数 max_length 使用滑动窗口的方法来找到连续自然数的最大长度,使得这些数的乘积包含的不同的素因子数量不超过 kk。
  • 在示例中,对于 n=10n=10 和 k=2k=2,连续数的最大长度是 4,对应的序列是 [6, 7, 8, 9],其乘积包含的不同的素因子是 {2, 3}。

这个算法的时间复杂度是 O(nn)O(nn​),因为我们需要对每个数进行素因子分解,而分解一个数的时间复杂度是 O(n)O(n​)。空间复杂度是 O(k)O(k),用于存储素因子集合。