题解:AcWing 868 筛质数

【题目来源】

AcWing:868. 筛质数 - AcWing题库

【题目描述】

给定一个正整数 \(n\),请你求出 \(1\sim n\) 中质数的个数。

【输入】

共一行,包含整数 \(n\)

【输出】

共一行,包含一个整数,表示 \(1\sim n\) 中质数的个数。

【输入样例】

8

【输出样例】

4

【解题思路】

image

【算法标签】

《AcWing 868 筛质数》 #数学知识# #质数# #筛质数#

【代码详解】

// 埃式筛法
#include <bits/stdc++.h>
using namespace std;

const int N = 1000005;  // 定义筛法上限

int primes[N], cnt;     // primes数组存储素数,cnt记录素数个数
bool st[N];             // 标记数组,false表示是素数,true表示不是素数

// 埃拉托斯特尼筛法求素数
void get_primes(int n)
{
    // 从2开始遍历到n
    for (int i = 2; i <= n; i++)
    {
        // 如果当前数未被标记为非素数
        if (!st[i])
        {
            primes[cnt++] = i;  // 将当前数加入素数数组
          
            // 标记当前素数的所有倍数为非素数
            for (int j = i + i; j <= n; j += i)
                st[j] = true;
        }
    }
}

int main()
{
    int n;  // 输入的上限值
    cin >> n;
  
    // 调用筛法函数获取素数
    get_primes(n);
  
    // 输出素数个数
    cout << cnt << endl;
  
    return 0;
}
// 线性筛
#include <bits/stdc++.h>
using namespace std;

const int N = 1000005;  // 定义筛法上限

int primes[N], cnt;     // primes数组存储素数,cnt记录素数个数
bool st[N];             // 标记数组,false表示是素数,true表示合数

// 线性筛法(欧拉筛)求素数
void get_primes(int n)
{
    // 从2开始遍历到n
    for (int i = 2; i <= n; i++)
    {
        // 如果i未被标记为合数,则i是素数
        if (!st[i])
            primes[cnt++] = i;  // 将i加入素数数组
      
        // 用当前已找到的素数筛选合数
        for (int j = 0; primes[j] <= n / i; j++)
        {
            st[primes[j] * i] = true;  // 标记素数的倍数为合数
          
            // 关键优化:当primes[j]是i的最小质因子时终止筛选
            if (i % primes[j] == 0)
                break;
        }
    }
}

int main()
{
    int n;  // 输入的上限值
    cin >> n;
  
    // 调用线性筛法函数获取素数
    get_primes(n);
  
    // 输出素数个数
    cout << cnt << endl;
  
    return 0;
}

【运行结果】

8
4
posted @ 2026-02-21 21:00  团爸讲算法  阅读(0)  评论(0)    收藏  举报