引言
本文将介绍素数筛法:
主要从他的原理, 证明, 代码, 优化来介绍
随后介绍和它有关的唯一分解定理, 以及相似的欧拉函数
素数筛法:
一个同辗转相除法同样古老的算法
原理: 如果x 是素数 那么2x, 3x, 4x……都不是素数, 所以如果我们从2开始往后筛, 筛到n, 这时候n没有被前面的任何数标记成不是素数, 那么n就是素数
证明:
第一点: 如果x 是素数 那么2x, 3x, 4x……都不是素数 这个很简单不多说
第二点: 所以如果我们从2开始往后筛, 筛到n, 这时候n没有被前面的任何数标记成不是素数, 那么n就是素数
反证法: 如果n 不是 素数, 那么必然存在a, b (a是素数) 使得 a*b = n, 而我们的数字是从小到大的, 所以在我们运行到a的时候必定会标记2a, 3a, 4a ……不是素数(这里边一定存在a * b), 表示n被其他数标记成了不是素数, 这与没有标记明显矛盾, 所以n一定是素数;
所以筛选素数的时候我们可以这样(这不是最终形态):
#include <cstdio>
#include <cstring>
const int N = 1000000 + 10;
bool isprime[N];
int prime[N];
void makeprime(int n) {
memset(isprime, 1, sizeof isprime);
isprime[1] = 0;
for(int i = 2; i < n; ++i) {
if(isprime[i]) for(int j = i+i; j < n; j += i)
isprime[j] = 0;
}
}
int getprime(int n) {
int k = 0;
for(int i = 1; i < n; ++i) {
if(isprime[i]) prime[k++] = i;
}
return k;
}
int main() {
makeprime(N);
int prime_size = getprime(N);