初学素数筛选,讲的不是特别详细,见谅,埃筛比较好理解,线性筛我讲的不太好理解

素数筛选法

在这里,最基本的那种筛选方法我就我说了,在这里主要介绍的是欧拉筛和埃筛

埃筛

埃筛就是从2开始找素数,然后把其倍数全部标记出来,这样就少了一部分数,然后找下一个素数3,继续找到其倍数,依次找,找的同时,把找到的素数存到定义要的数组中,最后就可以得到一个素数数组集合。


import java.util.LinkedList;
import java.util.Scanner;

public class Main_aishuai {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int n = sc.nextInt();
            LinkedList<Integer> list = new LinkedList<>();
            boolean[] booleans = new boolean[n + 1];
            for (int i = 2; i <= n; i++) {
                if (booleans[i] == false) {
                    list.add(i);
                    for (int j = i + i; j <= n; j += i) {
                        booleans[j] = true;
                    }
                }
            }
        }
    }
}

在这里我用的是链表存储,建议使用数值存储,有点算是偷懒,就用了链表。他的时间复杂度为o(nloglogn)
但是这种筛选方法还是慢,所有就有了欧筛,一种比埃筛更快的筛选方式。

欧拉筛

欧拉筛又叫线性筛,因为他的时间复杂度为o(n),欧拉筛的目的是消除埃筛有的数会被多次筛选而出现的,欧拉筛通过最小质因子来确定标记, if (i % a[j] == 0) break;就是关键,即不重复标记的关键。

           int n = sc.nextInt();
            boolean[] bool = new boolean[n + 1];
            int a[] = new int[n + 1];
            int count = 0;
            for (int i = 2; i <= n; i++) {
                if (bool[i] == false) {
                    a[count++] = i;
                }
                for (int j = 0; j < count && i * a[j] <= n; j++) {
                    bool[i * a[j]] = true;
                    if (i % a[j] == 0)
                        break;
                }

            }

下面说一下杭电2136题,这是一道关于素数的题,求的是一个数是由其他数相乘的到的,求其中的最大质因子。

Largest prime factor

Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 19782 Accepted Submission(s): 6787

Problem Description
Everybody knows any number can be combined by the prime number.
Now, your task is telling me what position of the largest prime factor.
The position of prime 2 is 1, prime 3 is 2, and prime 5 is 3, etc.
Specially, LPF(1) = 0.

Input
Each line will contain one integer n(0 < n < 1000000).

Output
Output the LPF(n).

Sample Input

1
2
3
4
5

Sample Output

0
1
2
1
3

Author
Wiskey

下面是代码,比较垃圾

import java.util.Scanner;

public class Main2136 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int count = 0;//记录素数因子的位置
        int[] bool = new int[1000001];//数组最长1000001
        for (int i = 2; i < 1000001; i++) {
            if (bool[i] == 0) {//判断是否是素数
                count++;
                for (int j = i; j <= 1000000; j += i) {//将所有i的倍数记录下来,他们目前的最大因子为count=1
                //通过for循环逐渐改变值
             
                    bool[j] = count;
                }
            }
        }
        while (sc.hasNext()) {
            int n = sc.nextInt();
            System.out.println(bool[n]);

        }
    }
}

  初始
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  0 0 0 0 0 0 0 0 0  0  0  0  0  0 0  0
  第一个素数2的时候
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  0 1 0 1 0 1 0 1 0  1 0  1  0  1 0  1
  第二个素数3的时候
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  0 1 2 1 0 2 0 1 2  1  0  2  0  1 2  1
  第三个数为4,跳过到素数5
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  0 1 2 1 3 2 0 1 2  3  0  2  0  1  3 1
  第四个数6跳过,到7
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  0 1 2 1 3 2 4 1 2  3  0  2  0  4 3  1
  以此类推
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值