素数

素性测试

素数:若整数 $n ( n > 1)$ 只有 $1$ 和 $n$ 两个因数,则 $n$ 为素数。

试除法

判断一个数 $n$ 是否为素数,最直接的办法是按照定义判断,依次看 $2,3,\cdots,n-1$ 能否整除 $n$,若能整除则 $n$ 为合数,都不能整除则 $n$ 为素数,算法时间复杂度为 $O(n)$。

 1// 素性测试
 2bool isPrime(int n) {
 3    if (n < 2) {
 4        return false;
 5    } else {
 6        for(int i = 2; i < n - 1; i++) {
 7            if (n % i == 0) {
 8                return false;
 9            }
10        }
11        return true;
12    }
13}

若 $n$ 为合数,则 $\exists s \geq t \in N_{+} 且 s \geq t > 1$ 使得 $n = st$, 于是有 $t \leq \sqrt{n}$,也就是说合数 $n$ 一定存在一个因数小于等于 $\sqrt{n}$。 因此我们只需要对 $2,3,\cdots,\sqrt{n}$ 判断是否能整除 $n$ 即可。因此上述算法时间复杂度可降为 $O(\sqrt{n})$.

 1// 素性测试
 2bool isPrime(int n) {
 3    if (n < 2) {
 4        return false;
 5    } else {
 6        for (int i = 2; i * i <= n; i++) {
 7            if (n % i == 0) {
 8                return false;
 9            }
10        }
11        return true;
12    }
13}

打印素数表

Eratosthenes 筛法

算法思想是用已知素数的倍数去过滤掉那些合数,算法复杂度为 $O(n \log{\log n})$.

 1#include <vector>
 2
 3using namespace std;
 4
 5// Eratosthenes 筛法返回小于等于 n 的素数表
 6vector<int> eratosthenes(int n) {
 7    vector<int> primes;
 8    if (n < 2) {
 9        return primes;
10    }
11    vector<int> check(n + 1);
12    for (int i = 2; i <= n; i++) {
13        if (!check[i]) {
14            primes.push_back(i);
15            for (int j = 2 * i; j <= n; j += i) {
16                check[j] = true;
17            }
18        }
19    }
20    return primes;
21}

Euler 筛法

Euler 筛法也称线性筛法,时间复杂度为 $O(n)$.

 1#include <vector>
 2
 3using namespace std;
 4
 5// Euler 筛法
 6vector<int> euler(int n) {
 7    vector<int> primes;
 8    if (n < 2) {
 9        return primes;
10    }
11    vector<int> check(n + 1);
12    for (int i = 2; i <= n; i++) {
13        if (!check[i]) {
14            primes.push_back(i);
15        }
16        for (int j = 0; j < primes.size() && i * primes[j] <= n; j++) {
17            check[i * primes[j]] = true;
18            if (i % primes[j] == 0) {
19                break;
20            }
21        }
22    }
23    return primes;
24}

素因子分解

 1#include <vector>
 2
 3using namespace std;
 4
 5// 素因子分解: 试除法
 6vector<pair<int, int>> getPrimeFactorization(int n) {
 7    // factorization[i][0] 和 factorization[i][1] 表示第 i 个素因子及其指数
 8    // 素因子从小到达排序
 9    vector<pair<int, int>> factorization;
10    for (int i = 2; i * i <= n; ++i) {
11        if (n % i == 0) {
12            int index = 0;
13            while (n % i == 0) {
14                n /= i;
15                ++index;
16            }
17            factorization.emplace_back(i, index);
18        }
19    }
20    if (n != 1) {
21        factorization.emplace_back(n, 1);
22    }
23    return factorization;
24}
下一页