解题报告:连续自然数乘积的素因子分解问题
问题理解
本题要求在给定的范围 [1, n] 内,找到一组连续的自然数,使得这些数的乘积最多包含 k 个不同的素因子。目标是找到这组连续自然数的最大长度。
关键点:
- 连续自然数:指的是不能重复且相邻数的差为1的一组正整数,例如
[2, 3, 4, 5]和[5, 6, 7]都是连续的取数。 - 素因子:一个数的素因子是指能整除该数的素数。例如,6的素因子是2和3。
- 最多包含
k个不同的素因子:意味着我们需要找到一组连续的自然数,使得它们的乘积的素因子种类不超过k。
数据结构选择
为了高效地解决这个问题,我们需要选择合适的数据结构来存储和处理素因子信息。
- 集合(Set):用于存储当前窗口内的素因子,以便快速判断素因子的种类数。
- 字典(Dictionary):用于记录每个素因子的出现次数,以便在移动窗口时更新素因子信息。
算法步骤
-
初始化:
- 定义一个函数
prime_factors用于计算一个数的所有素因子。 - 初始化一个字典
factor_count用于记录每个素因子的数量。 - 初始化两个指针
left和right,分别表示当前窗口的左右边界。 - 初始化一个变量
max_length用于记录当前找到的最大窗口长度。
- 定义一个函数
-
滑动窗口:
- 使用
right指针遍历[1, n]范围内的所有数。 - 对于每个数
right,计算其素因子并更新factor_count。 - 如果当前窗口内的素因子种类数超过
k,则移动left指针,直到素因子种类数不超过k。 - 在每次移动
left指针后,更新max_length。
- 使用
-
返回结果:
- 最终返回
max_length,即满足条件的连续自然数的最大长度。
- 最终返回
代码详解
from collections import defaultdict
def prime_factors(x):
factors = set()
d = 2
while d * d <= x:
while (x % d) == 0:
factors.add(d)
x //= d
d += 1
if x > 1:
factors.add(x)
return factors
def solution(n: int, k: int) -> int:
left = 1
max_length = 0
factor_count = defaultdict(int) # 记录每个素因子的数量
for right in range(1, n + 1):
# 更新右边界的素因子
factors = prime_factors(right)
for factor in factors:
factor_count[factor] += 1
# 检查不同素因子的数量
while len(factor_count) > k:
# 移动左边界并更新素因子
left_factors = prime_factors(left)
for factor in left_factors:
factor_count[factor] -= 1
if factor_count[factor] == 0:
del factor_count[factor]
left += 1
# 计算当前窗口的长度
max_length = max(max_length, right - left + 1)
return max_length
if __name__ == "__main__":
print(solution(10, 3) == 6)
print(solution(20, 5) == 12)
print(solution(100, 4) == 10)
代码详解:
- prime_factors 函数:用于计算一个数的所有素因子,并返回一个集合。
- solution 函数:
- 初始化
left指针为1,max_length为0,factor_count为空字典。 - 使用
right指针遍历[1, n]范围内的所有数。 - 对于每个数
right,计算其素因子并更新factor_count。 - 如果当前窗口内的素因子种类数超过
k,则移动left指针,直到素因子种类数不超过k。 - 在每次移动
left指针后,更新max_length。 - 最终返回
max_length。
- 初始化
测试样例解析
样例1:
- 输入:
n = 10, k = 3 - 输出:
6 - 解释:在
[1, 10]范围内,连续的自然数[2, 3, 4, 5, 6, 7]的乘积最多包含3个不同的素因子(2, 3, 5)。
样例2:
- 输入:
n = 20, k = 5 - 输出:
12 - 解释:在
[1, 20]范围内,连续的自然数[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]的乘积最多包含5个不同的素因子(2, 3, 5, 7, 11)。
样例3:
- 输入:
n = 100, k = 4 - 输出:
10 - 解释:在
[1, 100]范围内,连续的自然数[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]的乘积最多包含4个不同的素因子(2, 3, 5, 7)。
总结
本题通过滑动窗口和素因子分解的方法,有效地解决了在给定范围内找到连续自然数乘积的素因子种类数不超过 k 的问题。通过合理选择数据结构和算法步骤,我们能够在较短的时间内找到满足条件的最大长度。
关键点总结:
- 滑动窗口:通过左右指针的移动,动态调整窗口内的素因子种类数。
- 素因子分解:通过
prime_factors函数,高效地计算每个数的素因子。 - 字典记录:使用字典记录每个素因子的数量,便于快速更新和判断。