The Sieve of Eratosthenes (素数筛选法)
问题描述
给定一个正整数 $n$,输出不超过 $n$ 的全部素数。
算法描述
- 写出$2\cdots n$所有的数。
- 计算出 $m=\sqrt{n}$ ,把不超过 $m$ 的所有素数的倍数(不能是素数本身)全部删除,剩下的就是 $2\cdots n$中的素数。
算法复杂度
$O(n)$
正确性证明
命题:给定一个合数x,一定存在不超过 $\sqrt{x}$ 的素数 P,且 $x \% p=0$。
证明:我们从1开始找合数,设 $x$ 为第一个不满足上述条件的合数。因为 $x$ 是一个合数,因此存在 $a$,使得 $x \% a=0$。
(1)$a$是合数。因为$a$小于$x$,因此$a$满足:存在不超过 $\sqrt{a}$ 的素数$b$,且 $a \% b=0$。因为 $b<\sqrt{a}<\sqrt{x}$,因此 $x \% b=0$,与假设矛盾。
(2)$a$是素数。因此 $a>\sqrt{x}$,因此 $x=ka$。
1)$k$是合数。则同(1)的方法。
2)$k$是素数。则 $k<\sqrt{x}$,因为假设 $k\ge \sqrt{x}$,则 $ka>x$,与假设矛盾。
算法实现
1 public class Prime { 2 public static int sieve(int n){ 3 boolean[] arr = new boolean[n+1]; 4 for(int i=0;i<arr.length;i++) 5 arr[i] = true; 6 int bound = (int)Math.floor(Math.sqrt(n)); //根号n 7 for(int i=2;i<=bound;i++){ 8 if(arr[i]){ 9 for(int j=2;j*i<=n;j++){ 10 arr[i*j] = false; 11 } 12 } 13 } 14 int count = 0; 15 for(int i=2;i<arr.length;i++){ 16 if(arr[i]) { 17 count++; 18 System.out.println(i); 19 } 20 } 21 return count; 22 } 23 public static void main(String[] args) { 24 sieve(100); 25 } 26 }
孪生素数猜想
孪生素数:如果a,b是两个素数,且$a=b-2$,则称 $a$ 与 $b$ 是孪生素数。比如3与5是孪生素数。
孪生素数猜想:存在无穷多对孪生素数。
在2013年5月,张益唐证明了孪生素数猜想的弱化版本:存在无穷多对相差小于七千万的素数。