【算法基础:数学知识】4.1 质数

质数

定义质数是指在大于1的自然数中除了1和它本身以外不再有其他因数的自然数

也就是说一个数 > 1,而且它的因数只有 1 和 它本身,那么它就是质数。

例题列表

866. 试除法判定质数(质数的判定)

https://www.acwing.com/activity/content/problem/content/935/

在这里插入图片描述

import java.util.*;

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while (n-- != 0) {
            int a = sc.nextInt();
            System.out.println(isPrime(a)? "Yes": "No");
        }
    }

    static boolean isPrime(int x) {
        if (x <= 1) return false;
        for (int i = 2; i <= x / i; ++i) {      // 注意这里写成 i <= x / i,不要写成 i * i <= x
            if (x % i == 0) return false;
        }
        return true;
    }
}

当 n 比较接近 Integer.MAX_VALUE 时,如果使用 i * i <= n, i * i 可能会溢出。所以推荐写成 i <= n / i

时间复杂度是 O ( n ) O(\sqrt{n}) O(n )

867. 分解质因数

质因数(素因数或质因子)在数论里是指能整除给定正整数的质数。

https://www.acwing.com/problem/content/869/

在这里插入图片描述

从小到大枚举所有数,(注意:不需要枚举所有的质数,只要枚举所有的数即可。)
Q:为什么?
A:因为当枚举到 i 时,就意味着已经把从 2 ~ i - 1 的所有质因子都除干净了。(更详细的当枚举到 i 时,n 中不包含 2 ~ i - 1 中的数字作为因子,所以一定不会和 i 有共同的因子了。

import java.util.*;

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while (n-- != 0) {
            divide(sc.nextInt());
        }
    }

    static void divide(int x) {
        for (int i = 2; i <= x / i; ++i) {
            if (x % i == 0) {
                int s = 0;
                while (x % i == 0) {        // 把 x 中的 i 除干净
                    s++;
                    x /= i;
                }
                System.out.println(i + " " + s);
            }
        }
        if (x > 1) System.out.println(x + " " + 1);     // 注意要判断最后剩下的没被除掉的质因数
        System.out.println();
    }
}

n 中最多只包含 1 个 大于 n \sqrt{n} n 的质因子。
所以先枚举出所有小于等于 n \sqrt{n} n 的质因子,最后剩下的就是大于 n \sqrt{n} n 的那一个质因子。

时间复杂度是 n \sqrt{n} n 。(最好是 log ⁡ n \log{n} logn

868. 筛质数

关于筛质数的详细总结可见:【算法】数学相关知识总结

在这里插入图片描述

埃氏筛

从小到大进行枚举,每次枚举到一个质数,就把数据范围内它的所有倍数都删掉。

import java.util.*;

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        boolean[] f = new boolean[n + 1];
        Arrays.fill(f, true);
        int cnt = 0;
        for (int i = 2; i <= n; ++i) {
            if (f[i]) {
                ++cnt;
                for (int j = 2; i <= n / j; ++j) {
                    f[i * j] = false;
                }
            }
        }
        System.out.println(cnt);
    }
}

欧氏筛 / 线性筛

n只会被它的最小质因子筛掉

每次循环 j 是为了筛掉所有已经发现的质数的 i 倍,即 prime[j] 的意义是目前已经发现的第 j 个质数。

import java.util.*;

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), cnt = 0;
        int[] prime = new int[n + 1], st = new int[n + 1];
        for (int i = 2; i <= n; ++i) {
            if (st[i] == 0) prime[cnt++] = i;
            for (int j = 0; prime[j] <= n / i; ++j) {
                st[prime[j] * i] = 1;
                if (i % prime[j] == 0) break;
            }
        }
        System.out.println(cnt);
    }
}

相关链接

【算法】数学相关知识总结

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wei *

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值