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

22 阅读5分钟

问题描述

小M拿到一个数组,她可以进行多次操作,每次操作可以选择两个元素 aiai​ 和 ajaj​,并选择 aiai​ 的一个因子 xx,然后将 aiai​ 变为 ai/xai​/x,并将 ajaj​ 变为 aj×xaj​×x。她的目标是通过有限次操作,使得数组中的每个元素最多只包含一种素因子。

素因子的定义是:若 xx 能被素数 pp 整除,那么 pp 是 xx 的一个素因子。例如,1212 的素因子有 22 和 33。

你的任务是判断是否有可能通过有限次操作,使数组中的每个元素最多只包含一种素因子。如果可以,输出 "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'

好的!以下是代码的详细解答与逻辑分析:


代码说明

这段代码旨在判断一个整数数组中所有数字的素因子是否总数不超过给定的整数 n。具体流程如下:

  1. 遍历数组 a 中的每个数字。
  2. 对每个数字进行素因子分解,将分解得到的素因子存入一个集合 unique_factors 中。
  3. 使用集合的特性确保存储的素因子不重复。
  4. 比较集合中素因子的数量与 n 的大小,如果不超过则返回 "Yes",否则返回 "No"

代码实现

#include <iostream>
#include <vector>
#include <set>
using namespace std;

string solution(int n, const vector<int>& a) {
    set<int> unique_factors; // 用于存储所有出现过的素因子

    for (int x : a) {
        int y = x;
        for (int i = 2; i * i <= y; i++) {
            if (y % i == 0) {
                unique_factors.insert(i); // 将素因子添加到集合中
                while (y % i == 0) {
                    y /= i; // 除去所有 i 的倍数
                }
            }
        }
        if (y != 1) {
            unique_factors.insert(y); // 如果剩余的 y 是一个大于 1 的素数
        }
    }

    return unique_factors.size() <= n ? "Yes" : "No";
}

int main() {
    // 测试样例
    cout << solution(4, {1, 2, 3, 4}) << endl; // 输出 Yes
    cout << solution(2, {10, 12}) << endl;     // 输出 No
    cout << solution(3, {6, 9, 15}) << endl;   // 输出 Yes

    return 0;
}

逻辑分析

素因子分解

  1. 遍历数组:
    对数组 a 中每个数字 x 进行处理。

  2. 分解素因子:
    对于每个数字 x,从 2 开始试除,直到 sqrt(x)

    • 如果 x 能被 i 整除,将 i 添加到集合中。
    • 使用 while 循环移除所有 i 的倍数,确保分解完毕后不再重复处理。
    • 如果最终剩余的 x > 1,说明它是一个大于 1 的素数,也需要添加到集合中。

集合存储

  • 使用 set 数据结构存储素因子,能够自动去重。例如,分解 6 = 2 * 3,会将 23 存入集合,而不会出现重复。

结果判断

  • 集合的大小等于分解得到的不同素因子的数量。如果这个数量小于或等于 n,则返回 "Yes";否则返回 "No"

测试用例分析

测试用例 1

  • 输入:solution(4, {1, 2, 3, 4})
  • 分解得到的素因子集合为 {2, 3}
  • 集合大小为 2,小于 n = 4,输出 "Yes"

测试用例 2

  • 输入:solution(2, {10, 12})
  • 分解得到的素因子集合为 {2, 3, 5}
  • 集合大小为 3,大于 n = 2,输出 "No"

测试用例 3

  • 输入:solution(3, {6, 9, 15})
  • 分解得到的素因子集合为 {2, 3, 5}
  • 集合大小为 3,等于 n = 3,输出 "Yes"

优化建议

  1. 特殊情况处理:

    • 如果数组全为 1,可以直接返回 "Yes",因为 1 没有素因子。
  2. 性能优化:

    • 如果输入的数字较大,可以引入快速素因子分解算法,例如欧拉筛。
  3. 输入验证:

    • 当前代码未处理异常输入,例如空数组或负数。
    • 归纳总结

核心思想

  1. 素因子分解:

    • 将一个整数分解为多个素数的乘积,这是许多算法和数学理论的基础。
    • 使用试除法可以有效地找到所有素因子,结合集合(set)确保去重。
  2. 集合的应用:

    • 使用集合存储素因子,实现了自动去重的功能,避免冗余计算。
    • 集合的大小可以直接反映不同素因子的总数。
  3. 优化问题:

    • 判断是否满足给定条件(素因子总数是否不超过 n),属于一种限制性优化问题。

生活中的应用

  1. 密码学:

    • 素因子分解在密码学中有重要应用,特别是在 RSA 加密算法中,两个大素数的乘积用于生成公钥和私钥。
    • 由于分解大整数的素因子非常困难,这种加密方法非常安全。
  2. 数据压缩:

    • 在数据处理中,类似素因子分解的思想可以用于分析数据的组成结构(例如频率分解),以优化存储和压缩。
  3. 分解问题:

    • 在供应链管理或制造业中,将复杂任务分解为多个简单任务(类似于素因子分解)可以提高效率。例如,分析不同材料的来源,优化生产流程。
  4. 统计与计数:

    • 在生活中统计独特元素(类似素因子)也很常见,例如:

      • 统计朋友圈中共同好友的人数。
      • 分析不同文章中的关键词。
  5. 游戏与娱乐:

    • 在某些益智游戏中,素因子分解和集合操作可用于设计问题,如数字分解谜题或数独的某些变体。

总结

素因子分解与集合操作的结合体现了数学在算法和逻辑中的优雅性。这种思想广泛应用于密码学、优化、数据分析等领域,同时也能帮助我们在生活中解决一些计数和分解问题,体现了数学的实用性和趣味性。