问题描述
小M拿到一个数组,她可以进行多次操作,每次操作可以选择两个元素 和 ,并选择 的一个因子 ,然后将 变为 ,并将 变为 。她的目标是通过有限次操作,使得数组中的每个元素最多只包含一种素因子。
素因子的定义是:若 能被素数 整除,那么 是 的一个素因子。例如, 的素因子有 和 。
你的任务是判断是否有可能通过有限次操作,使数组中的每个元素最多只包含一种素因子。如果可以,输出 "Yes",否则输出 "No"。
测试样例
样例1:
输入:
n = 4 ,a = [1, 2, 3, 4]输出:'Yes'
样例2:
输入:
n = 2 ,a = [10, 12]输出:'No'
样例3:
输入:
n = 3 ,a = [6, 9, 15]输出:'Yes'
思路
1、观察题目和用例:
(1)每次操作可以选择两个元素 和 ,并选择 的一个因子 ,然后将 变为 ,并将 变为 。
假设我们存在两个数:10 和 36
依题,我们需要计算这两个数的素因子(为素数的因子),10为2、5,36为2、2、3、3
tips:题目要求最终答案每个元素只包含一个素因子,因此我们尽量将所有因子分解为素因子
对于每次操作,将 变为 ,并将 变为 ,我们可以将每个元素视作素因子的集合,每次操作的本质就是将一个集合中的元素移动到另一个集合中
如10(2,5)和36(2,2,3,3),可以变为20(2,2,5)和18(2,3,3)
(2)使数组中的每个元素最多只包含一种素因子
Q:什么情况下一个元素只存在一个素因子?
A:
情况一:这个元素本身就是素数(如7)
情况二:这个元素是单一素因子的乘积(如、)
综上,为了检查是否可以让每个元素都包含一个素因子,我们应当尽量将相同的素因子移动到同一个元素(集合)中,可以转化为所有元素的素因子的个数不超过元素的个数
如样例3:, 素因子为,三个元素,三种素因子,每个素因子最终都可以归到一个集合中,因此结果是"Yes"
如样例2:, 素因子为,两个元素,三种素因子,每个素因子无法归到一个集合中,因此结果是"No"
(3)如何快速计算素因子
可以使用埃氏筛或欧拉筛(线性筛)
本题解使用埃式筛,由于题目数据较弱,只需要筛出20往前的素数即可
埃氏筛大致逻辑如下
1、 创建一个从2到给定数字n的列表,初始化为全为“素数”(未被筛掉)。
2、 从列表中找到第一个未被标记的数字,这一定是一个素数。
3、 标记这个数字的所有倍数为“非素数”。
4、 重复步骤2和步骤3,直到处理的数字超过范围。
5、 剩下未被标记的数字即为素数。
// 保存素数
static List<Integer> p = new ArrayList<>();
static {
// 判断一个i是否是素数,本题范围为20以内即可AC
boolean[] temp = new boolean[20];
// 初始化
Arrays.fill(temp, true);
temp[0] = false;
temp[1] = false;
for (int i = 2; i < temp.length; i++) {
for(int j = 2;i*j<temp.length;j++){
temp[i*j] = false;
}
}
for (int i = 0; i < temp.length; i++) {
// 是素数
if (temp[i]) {
p.add(i);
}
}
}
2、大致逻辑
- 预处理素数
- 遍历每个元素,统计每个元素中出现的素因数
- 计算出现过的素因数个数是否<=元素个数
代码
static List<Integer> p = new ArrayList<>();
static {
boolean[] pp = new boolean[10000];
Arrays.fill(pp, true);
pp[0] = false;
pp[1] = false;
for (int i = 2; i < pp.length; i++) {
for (int j = 2; i * j < pp.length; j++) {
pp[i * j] = false;
}
}
for (int i = 0; i < pp.length; i++) {
if (pp[i]) {
p.add(i);
}
}
}
public static String solution(int n, int[] a) {
// 统计素因子个数
Set<Integer> set = new HashSet<>();
for (int i = 0; i < a.length; i++) {
for (int j = 0; p.get(j) <= a[i]; j++) {
// 是因子
if (a[i] % p.get(j) == 0) {
set.add(p.get(j));
}
}
}
return set.size() <= a.length ? "Yes" : "No";
}
public static void main(String[] args) {
System.out.println(solution(4, new int[]{1, 2, 3, 4}).equals("Yes"));
System.out.println(solution(2, new int[]{10, 12}).equals("No"));
System.out.println(solution(3, new int[]{6, 9, 15}).equals("Yes"));
}