试除法
要判断自然数 x 是否为素数,不断尝试小于 x 大于1的自然数,只要有一个能整除, x 不是素数,反之, x 是素数
一、从 2 到 n - 1
是我最开始想到的最最基础的方法
void prime(int n) {
for(int x = 2; x <= n; x++) {
for(int y = 2; y < x; y++) {
if(x % y == 0) break;
}
if(y == x) printf("%d ", x);
}
}
二、从 2 到 √n
刚开学的时候学的
void prime(int n) {
for(int x = 2; x <= n; x++) {
int k = sqrt(x);
for(int y = 2; y < k; y++) {
if(x % y == 0) break;
}
if(y == k) printf("%d ", x);
}
}
三、小于 n 的素数
写这个的时候刚学到的
int pri[n];
void prime(int n) {
int i = 1;
memset(pri, 0, sizeof(pri));
pri[0] = 2;
for(int x = 3; x <= n; x++) {
for(int y = 0; y < i; y++) {
if(x % pri[y] == 0) break;
}
if(y == i) pri[i++] = x;
}
}
埃氏筛
筛法会快很多,但是埃氏筛容易重复筛到一个数
比如 6 ,在 2 的倍数时已经被筛去了,在 3 的倍数的时候还会再筛一遍
时间复杂度O(nloglogn)
bool isprime[n];/*是否为素数*/
int prime[n];
void Is(int n){
int num = 0;
memset(isprime, true, sizeof(isprime));
for(int i = 2; i <= n; i++){
if(isprime[i]) {
prime[num++] = i;
for(int j = i + i; j <= n; j += i){
isprime[j] = false;/*把素数的倍数判为非素数*/
}
}
}
}
欧拉筛
线性筛,与埃氏筛相比效率更高
欧拉筛将合数分解为 (最小质因数 * 合数) 的形式,通过最小质因数来判断当前合数是否已被标记
时间复杂度为O(n)
bool isprime[n];
int prime[n];
void Es(int n){
int num = 0;
memset(isprime, true, sizeof(isprime));
for(int i = 2; i < n; i++){
if(isprime[i]) prime[num++] = i/*若未被筛去,为素数,记录该素数*/
for(int j = 0; j < num; j++){
if(i * prime[j] > n) break;/*超出范围时跳出循环*/
isprime[i * prime[j]] = false;
if(i % prime[j] == 0) break;/*当i 是prime[j]的整数倍时,i * prime[j+1] 是 prime[j]
的整数倍,为避免重复标记,跳出循环*/
}
}
}