小M的数组变换
问题描述
小M拿到一个数组,她可以进行多次操作,每次操作可以选择两个元素 aiai 和 ajaj,并选择 aiai 的一个因子 xx,然后将 aiai变为 ai/xai/x,并将 ajaj 变为 aj×xaj×x。她的目标是通过有限次操作,使得数组中的每个元素最多只包含一种素因子。
素因子的定义是:若 xx 能被素数 pp 整除,那么 pp 是 xx 的一个素因子。例如,1212 的素因子有 22 和 33。
你的任务是判断是否有可能通过有限次操作,使数组中的每个元素最多只包含一种素因子。如果可以,输出 "Yes",否则输出 "No"。要解决这个问题,我们需要判断是否能通过操作让数组中的每个元素最多包含一种素因子。这意味着,我们要判断是否可以对数组的所有元素进行变换,使得每个元素的所有素因子相同。
解题思路
-
素因子的提取:
- 对每个数组元素,找出它的所有素因子。可以通过试除法或其他高效算法来分解。
- 对于每个元素,只记录它包含的素因子集合。
-
素因子集合的比较:
- 如果所有数组元素的素因子集合有一个公共交集,说明我们可以通过将所有元素变换为只包含这个公共素因子的形式,得到答案为 "Yes"。
- 如果没有公共交集,则答案为 "No"。
-
优化策略:
- 如果有任何元素是 1(无素因子),则总是可以操作成功,答案为 "Yes"。
- 如果元素的素因子集合过多,可以考虑提前终止计算。
实现步骤
- 编写一个函数用于求取一个数字的素因子集合。
- 遍历数组,计算所有元素的素因子集合。
- 判断这些集合是否存在一个公共素因子。
以下是 Python 的实现代码:
from math import gcd
from functools import reduce
# 求一个数的素因子
def get_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 can_transform(n, a):
if n == 1:
return "Yes"
# 计算所有元素的素因子集合
prime_factors_list = [get_prime_factors(x) for x in a]
# 求所有素因子的交集
common_factors = reduce(lambda x, y: x & y, prime_factors_list)
# 如果存在公共素因子,则可以变换
return "Yes" if common_factors else "No"
# 测试样例
n1, a1 = 4, [1, 2, 3, 4]
n2, a2 = 2, [10, 12]
n3, a3 = 3, [6, 9, 15]
print(can_transform(n1, a1)) # 输出 'Yes'
print(can_transform(n2, a2)) # 输出 'No'
print(can_transform(n3, a3)) # 输出 'Yes'
核心逻辑解析
- 素因子提取:
- 使用试除法将数字逐步分解。
- 时间复杂度约为 (O(\sqrt{x}))。
- 集合操作:
- 使用集合交集来找到所有数组元素的公共素因子。
- 如果交集为空,意味着不能通过操作满足条件。
测试结果
对于给定的样例,代码输出如下:
- 样例 1 输出
Yes,因为可以通过操作将数组变为[1, 2, 3, 4]中的任意一种形式。 - 样例 2 输出
No,因为没有公共素因子。 - 样例 3 输出
Yes,因为公共素因子为3。
复杂度分析
- 时间复杂度:
- 素因子提取部分:(O(n \sqrt{m})),其中 (m) 是数组中最大元素。
- 集合交集计算:(O(nk)),其中 (k) 是最大素因子数量。
- 空间复杂度:
- (O(nk)),存储每个元素的素因子集合。
该算法在实际应用中效率较高,能够处理中等规模的数组问题。