Prime

Posted by Liao on 2020-03-22

一、试除法求素数

(通常会超时)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool isPrime(int n){
for(int i = 2; i <= sqrt(n); i++){
if(n%i==0)
return false;
}
return true;
}
int countPrimes(int n) {
if(n == 0 || n == 1)
return 0;
int cnt = 0;
for(int i = 2; i < n; i++){
if(isPrime(i))
cnt++;
}
return cnt;
}

二、埃氏筛(厄拉多塞筛法)

可以计算n<=10^7的数

1
2
3
4
5
6
7
8
9
10
11
12
13
int countPrimes(int n) {
vector<bool>vis(n,false);
int cnt = 0;
for(int i = 2; i < n; i++){
if(!vis[i]){
cnt++;
for(int j = i+i; j < n; j += i){
vis[j] = true;
}
}
}
return cnt;
}

预处理素数筛:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const mx = 1000 // 根据题目数据范围来定

var primes = []int{0} // 哨兵,避免二分越界:var primes = make([]int, 0)

func init() { // 预处理素数
isPrime := [mx]bool{}
for i := 2; i < mx; i++ {
if !isPrime[i] {
primes = append(primes, i)
for j := i * i; j < mx; j += i {
isPrime[j] = true
}
}
}
fmt.Println(primes) // 存储素数
}

三、线性筛(欧拉筛)

在数据量比较大的时候,线性筛的效率更高。

算法思想:每个合数只被划掉一次,因此划去 每个数x 乘上<=x的最小质因子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const mx = 1e6 + 1

var primes = make([]int, 0)

func init() {
isPrime := [mx]bool{}
for i := 2; i < mx; i++ {
if !isPrime[i] {
primes = append(primes, i)
}
for _, p := range primes {
if i*p >= mx {
break
}
isPrime[i*p] = true
if i%p == 0 { // p是i的第一个lpf 最小质因子
break
}
}
}
}