小M的数组变换题解 | 豆包MarsCode AI 刷题

76 阅读4分钟

问题分析

题目要求通过有限次操作,使得数组中的每个元素最多只包含一种素因子。可以选择两个元素 aiai​ 和 ajaj​,选择 aiai​ 的一个因子 xx,然后将 aiai​ 变为 ai/xai​/x,将 ajaj​ 变为 aj×xaj​×x。目标是每个数组元素最多只包含一种素因子。我们需要判断是否可以通过有限次操作实现这一目标。

思路分析

  1. 操作说明:

    • 对于每对 aiai​ 和 ajaj​,我们可以选择 aiai​ 的一个因子 xx,然后将 aiai​ 除以 xx,将 ajaj​ 乘以 xx。
    • 如果 aiai​ 和 ajaj​ 之间的因子共享结构不同,是否能通过这些操作将其变成一个只包含相同素因子的数?这需要考虑到数的因数分解以及如何在两个数之间迁移因子。
  2. 关键点:

    • 数字的因数结构:每个数可以分解成素因子的乘积。比如,12 可以分解为 22×322×3,那么它有两个素因子 2 和 3。
    • 要求每个数最多包含一个素因子。为了满足这一要求,我们需要将数组中的每个数转换为仅包含一种素因子的数。
  3. 考虑能否实现目标:

    • 通过操作可以改变数的因子结构,但要注意,在每次操作后,两个数的因子结构总是会变化。
    • 关键在于确定是否可以把所有数的素因子合并到一起,且最终每个数只包含一个素因子。
  4. 解题策略:

    • 将所有数的素因子提取出来:  对于每个数,提取它的所有素因子。
    • 分析因子分布:  判断是否可以将数组中的数变成每个数只包含相同的素因子。

具体步骤

  1. 对每个数进行素因子分解,记录它的所有素因子。
  2. 统计素因子的出现情况,看是否可以通过操作让每个数仅包含一个素因子。
  3. 判断是否能够实现目标:  如果一个素因子出现在多个数中且能够通过操作将它们转化为仅包含该素因子的数,那么答案是 "Yes";否则,答案是 "No"。

算法实现

  1. 素因子分解:  用埃拉托斯特尼筛法预先计算所有小于等于最大数的素数。
  2. 素因子统计:  对每个数进行素因子分解,记录每个素因子出现的次数。

代码实现

pythonCopy Code
import math
from collections import defaultdict

# 求一个数的素因子
def prime_factors(n):
    factors = set()
    # 处理 2
    while n % 2 == 0:
        factors.add(2)
        n //= 2
    # 处理奇数
    for i in range(3, int(math.sqrt(n)) + 1, 2):
        while n % i == 0:
            factors.add(i)
            n //= i
    # 如果n是质数且大于2
    if n > 2:
        factors.add(n)
    return factors

# 主函数
def can_make_single_prime_factor(nums):
    # 字典存储每个素因子出现在多少个数中
    prime_count = defaultdict(int)
    
    # 对每个数,分解它的素因子
    for num in nums:
        factors = prime_factors(num)
        for factor in factors:
            prime_count[factor] += 1
    
    # 判断能否通过操作,使得每个数只包含一个素因子
    for factor, count in prime_count.items():
        if count > 1:
            return "No"
    
    return "Yes"

# 输入读取
n = int(input())
nums = list(map(int, input().split()))

# 输出结果
print(can_make_single_prime_factor(nums))

解释

  1. 素因子分解:

    • 使用 prime_factors(n) 函数对每个数进行素因子分解。对于每个数,我们从 2 开始不断试除,直到完全分解为素数因子。
  2. 素因子统计:

    • 使用字典 prime_count 来记录每个素因子出现的次数。如果某个素因子出现超过一次,说明它出现在多个不同的数中,我们需要判断是否能够通过操作将它们转换为只包含该素因子的数。
  3. 判断条件:

    • 如果某个素因子出现在多个不同的数中,并且我们无法通过操作将它们分配到不同的数中,使得每个数只包含一个素因子,则输出 "No"。
    • 否则,输出 "Yes"。

复杂度分析

  1. 时间复杂度:

    • 对于每个数,我们要进行素因子分解。每次素因子分解的时间复杂度是 O(n)O(n​),其中 nn 是数的大小。
    • 如果数组的长度是 mm,最大数是 NN,那么总的时间复杂度是 O(m×N)O(m×N​)。
  2. 空间复杂度:

    • 我们使用字典 prime_count 来存储每个素因子的出现次数,最坏情况下空间复杂度为 O(k)O(k),其中 kk 是素因子的个数。

示例

输入:

Copy Code
5
12 18 15 30 45

输出:

Copy Code
Yes

解释:

  • 12 的素因子是 {2, 3}
  • 18 的素因子是 {2, 3}
  • 15 的素因子是 {3, 5}
  • 30 的素因子是 {2, 3, 5}
  • 45 的素因子是 {3, 5}

在这个例子中,通过合适的操作,所有的数可以最终变为只有一个素因子的数。所以输出 "Yes"。

输入:

Copy Code
4
6 10 15 21

输出:

Copy Code
No

解释:

  • 6 的素因子是 {2, 3}
  • 10 的素因子是 {2, 5}
  • 15 的素因子是 {3, 5}
  • 21 的素因子是 {3, 7}

在这个例子中,无法通过操作使得每个数只包含一个素因子。