• 分解质因数——AcWing 197. 阶乘分解


    分解质因数

    定义

    • 质因数分解是将一个大于1的整数写成一些质数的乘积的过程。
    • 每个合数(即非质数的整数)都有唯一的一种质因数分解方式,不计因子的顺序。

    运用情况

    • 数学运算:如求最大公约数(GCD)和最小公倍数(LCM)时,质因数分解非常有用。
    • 简化分数:通过质因数分解分子和分母,可以更容易地约简分数。
    • 解方程:在解决某些代数方程时,质因数分解可以帮助找到未知数的值。
    • 算术基本定理:每个大于1的整数要么是一个质数,要么可以唯一地表示为一组质数的乘积。

    注意事项

    • 分解时,应从最小的质数开始尝试除法,通常先除以2,然后是3,接着是5等。
    • 当一个数不能被任何小于它的平方根的质数整除时,这个数就是质数。
    • 质因数分解可能需要多次尝试不同的质数,直到所有因子都被分解出来。

    解题思路

    1. 选择最小的质数:从2开始,看它是否能整除给定的数。
    2. 持续除法:如果可以整除,就不断除以这个质数,直到不能再整除为止。
    3. 移动到下一个质数:一旦当前的质数不能整除了,就尝试下一个质数(例如3,5,7...)。
    4. 重复步骤:继续上述过程,直到最后剩下的数是一个质数。
    5. 记录结果:将所有的质数因子按照它们出现的次数记录下来。

    AcWing 197. 阶乘分解 

    题目描述

    197. 阶乘分解 - AcWing题库

    运行代码

    1. #include
    2. using namespace std;
    3. const int MAXN = 1000006;
    4. int primes[MAXN], cnt;
    5. bool st[MAXN];
    6. void get_primes(int n) {
    7. for (int i = 2; i <= n; i++) {
    8. if (!st[i]) primes[cnt++] = i;
    9. for (int j = 0; primes[j] * i <= n; j++) {
    10. st[primes[j] * i] = true;
    11. if (i % primes[j] == 0) break;
    12. }
    13. }
    14. }
    15. int main() {
    16. int n;
    17. cin >> n;
    18. get_primes(n);
    19. int c[MAXN] = {0};
    20. // 优化:只计算每个质数在 n! 中的出现次数
    21. for (int i = 0; i < cnt; i++) {
    22. int p = primes[i];
    23. int num = 0;
    24. for (int j = p; j <= n; j += p) {
    25. int x = j;
    26. while (x % p == 0) {
    27. num++;
    28. x /= p;
    29. }
    30. }
    31. c[i] = num;
    32. }
    33. for (int i = 0; i < cnt; i++) {
    34. if (c[i]) cout << primes[i] << " " << c[i] << endl;
    35. }
    36. return 0;
    37. }

    代码思路

    1. 初始化和获取质数:

      • get_primes函数使用了埃拉托斯特尼筛法(Sieve of Eratosthenes)来找出从2到n之间的所有质数,并存储在primes数组中。
      • st数组用于标记哪些数已经被筛掉(即非质数),而cnt用于跟踪已经找到的质数数量。
    2. 计算质因数在n!中的幂次:

      • 主函数main中,首先读入一个整数n,然后调用get_primes函数来获得所有不大于n的质数。
      • 接着,对于每一个质数p,程序计算出pn!中作为因子出现了多少次。
      • 这是通过遍历从pn的每个数,检查每个数能够被p整除多少次来实现的。每次能够整除时,计数器num增加,直到该数不再能被p整除。
    3. 输出结果:

      • 最后,遍历所有找到的质数及其在n!中出现的次数,并将它们输出。如果某个质数在n!的质因数分解中出现,则输出该质数及其对应的次数。

    注意:代码中的注释“优化:只计算每个质数在 n! 中的出现次数”意味着,代码并没有直接计算n!,而是计算了n!的质因数分解,这比直接计算阶乘更有效率,因为阶乘的值会变得非常大,可能会超出计算机可以处理的范围。

    改进思路

    其它代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. const int N = 1000010;
    7. int primes[N], cnt;
    8. bool st[N];
    9. void init(int n)
    10. {
    11. for (int i = 2; i <= n; i ++ )
    12. {
    13. if (!st[i]) primes[cnt ++ ] = i;
    14. for (int j = 0; primes[j] * i <= n; j ++ )
    15. {
    16. st[i * primes[j]] = true;
    17. if (i % primes[j] == 0) break;
    18. }
    19. }
    20. }
    21. int main()
    22. {
    23. int n;
    24. cin >> n;
    25. init(n);
    26. for (int i = 0; i < cnt; i ++ )
    27. {
    28. int p = primes[i];
    29. int s = 0;
    30. for (int j = n; j; j /= p) s += j / p;
    31. printf("%d %d\n", p, s);
    32. }
    33. return 0;
    34. }

    代码思路

    1. 初始化质数列表:

      • init函数使用埃拉托斯特尼筛法(Sieve of Eratosthenes)来生成小于等于nn的所有质数,并存储在primes数组中。
      • st数组用于标记哪些数已被筛去(即已知的合数)。
      • 当遇到一个新的质数ii,它会被添加到primes数组中,并且所有它的倍数都会被标记为合数。
    2. 计算质因数在n!n!中的幂次:

      • main函数中,首先读取一个整数n,然后调用init函数生成所有小于等于n的质数。
      • 遍历生成的质数列表,对于每个质数pp,使用一个循环计算pp在n!n!中作为因子出现的总次数。
      • 这个次数可以通过不断除以pp并累加商的方式计算,直到商小于1为止。具体地,对于每个pp,s初始化为0,然后使用一个循环,每次将j除以p,并将商加到s上,直到j不足以再被p整除。
    3. 输出结果:对于每个质数pp和它在n!n!中出现的次数ps,使用printf函数输出这对质数和次数。

    代码优化点

    • 使用Legendre公式计算每个质数在n!n!中的幂次,避免了原始代码中对于每个数都做一次完整的质因数分解,大大减少了计算量。
    • 使用printfscanf(虽然这里只用了cin)通常比coutcin快,尤其是在大量数据的输入输出时。
  • 相关阅读:
    Scss
    C++类详解
    I2C3挂载wm8960音频芯片
    BiliBili 阴阳师主题 前端技术展示
    2022最新最全Java 进阶资料合集
    要写文档了,emmm,先写个文档工具吧——DocMarkdown
    【OCR】合同上批量贴印章
    《 Python List列表全实例详解系列(五)》——修改元素(修改单个、修改一组)
    【滤波跟踪】基于UKF与KF实现单目标无杂波环境下二维雷达量测的目标跟踪算法附matlab代码
    记录一个困难
  • 原文地址:https://blog.csdn.net/u014114223/article/details/140417628