57、筛质数

筛质数

题目描述

给定一个正整数n,请你求出1~n中质数的个数。

输入格式

共一行,包含整数n。

输出格式

共一行,包含一个整数,表示1~n中质数的个数。

数据范围

1 ≤ n ≤ 1 0 6 1≤n≤10^6 1n106

输入样例:

8

输出样例:

4

Solution

  1. 埃氏筛法,时间复杂度O(nloglogn)

用质数筛去所有质数的倍数。

import java.util.*;

class Main{
    public static int getPrime(int n){
        int cnt = 0;
        // flag 表示 i 是否是合数
        boolean[] flag = new boolean[n + 10];
        // 用质数来筛合数
        int[] p = new int[n + 10];
        for(int i = 2; i <=n; i++){
            if(flag[i]) continue;
            p[cnt++] = i;
            // i 是质数,筛掉 i 的所有倍数
            for(int j = i + i; j <= n; j = j + i){
                flag[j] = true;
            }
        }
        return cnt;
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int cnt = getPrime(n);
        System.out.println(cnt);
    }
}
  1. 线性筛法,时间复杂度O(n)

每个合数只会被最小质数筛掉。

import java.util.*;

class Main{
    public static int getPrime(int n){
        int cnt = 0;
        // flag 表示 i 是否是合数
        boolean[] flag = new boolean[n + 10];
        // 用质数来筛合数
        int[] p = new int[n + 10];
        for(int i = 2; i <=n; i++){
            // 每个i都要遍历,不能跳过
            // 如果 i 是质数的花,加入数组
            if(!flag[i]) p[cnt++] = i;
            // i 是质数,筛掉 i 的所有倍数
            for(int j = 0; p[j] <= n / i; j ++){
                // 用质数筛去合数
                flag[i * p[j]] = true;
                // i % p[j] == 0 表示 p[j] 是 i 的最小质因子 当然也是 i * p[j] 的最小质因子
                // 这个啥时候就要break了,否则就用不是最小的质因子来筛合数了
                // i % p[j] != 0 表示 p[j] 小于 i 的最小质因子,当然是 i * p[j] 的最小质因子
                if(i % p[j] == 0) break;
            }
        }
        return cnt;
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int cnt = getPrime(n);
        System.out.println(cnt);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值