素数筛选法
在这里,最基本的那种筛选方法我就我说了,在这里主要介绍的是欧拉筛和埃筛
埃筛
埃筛就是从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
以此类推