各种求n以内素数的方法【试除法、埃氏筛、欧拉筛】

试除法

要判断自然数 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] 
      的整数倍,为避免重复标记,跳出循环*/
    }
  }
}

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值