题解:洛谷 P5736 质数筛

【题目来源】

洛谷:P5736 【深基7.例2】质数筛 - 洛谷

【题目描述】

输入 \(n\) 个不大于 \(10^5\) 的正整数。要求全部储存在数组中,去除掉不是质数的数字,依次输出剩余的质数。

【输入】

第一行输入一个正整数 \(n\),表示整数个数。

第二行输入 \(n\) 个正整数 \(a_i\),以空格隔开。

【输出】

输出一行,依次输出 \(a_i\) 中剩余的质数,以空格隔开。

【输入样例】

5
3 4 5 6 7

【输出】

3 5 7

【核心思想】

  1. 问题分析:给定 \(n\) 个不大于 \(10^5\) 的正整数,要求筛选出其中的质数并按原顺序输出。这是最基础的质数判定与筛选问题,核心是实现一个高效的质数判断函数,然后遍历数组依次判断。

  2. 算法选择

    • 试除法判定质数:对于每个数 \(x\),检查从 \(2\)\(\sqrt{x}\) 的所有整数是否能整除 \(x\)。若能整除则不是质数,否则是质数。时间复杂度为 \(O(\sqrt{x})\),对于 \(x \le 10^5\) 完全可行。
    • 优化:只需检查到 \(\sqrt{x}\),因为若 \(x\) 有大于 \(\sqrt{x}\) 的因子,则必然有小于 \(\sqrt{x}\) 的对应因子。代码中使用 i <= n / i 避免浮点数运算。
  3. 关键步骤

    • 读入:读取 \(n\),然后循环读取 \(n\) 个整数。
    • 质数判断:对每个数调用 is_prime(x)
      • \(x < 2\),返回 false
      • \(i = 2\)\(i \le x / i\),若 \(x \% i == 0\),返回 false
      • 否则返回 true
    • 输出:若是质数则输出该数,用空格分隔。
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n \sqrt{\max a_i})\)\(n \le 10^5\)\(a_i \le 10^5\),约 \(10^5 \times 316 = 3.16 \times 10^7\),可接受。
    • 空间复杂度:\(O(1)\),只使用常数空间。
  5. 质数判定与优化

    • 试除法:最直观的质数判定方法,适合单个数或少量数的判断。
    • 边界处理\(1\) 不是质数,需特殊处理。
    • 循环条件i <= x / i 等价于 i * i <= x,但可以避免 \(i \times i\) 溢出。
    • 适用场景:这类“质数筛”问题常见于入门阶段,用于练习函数定义和循环优化。

【算法标签】

普及- #质数

【代码详解】

#include <bits/stdc++.h>  // 包含标准库头文件(万能头文件)
using namespace std;      // 使用标准命名空间

// 函数声明:素数判断函数
bool fun(int n);

int main()
{
    int n;               // 定义变量:数字个数
    int a[105];          // 定义数组:存储输入的数字序列

    cin >> n;            // 输入数字个数

    // 输入数字序列
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }

    // 遍历数组,输出素数
    for (int i = 1; i <= n; i++)
    {
        if (fun(a[i]))   // 如果是素数
        {
            cout << a[i] << " ";  // 输出该素数
        }
    }

    return 0;            // 程序正常结束
}

/**
 * 素数判断函数
 * @param n 待判断的数字
 * @return 如果是素数返回true,否则返回false
 */
bool fun(int n)
{
    if (n <= 1)         // 小于等于1的数不是素数
    {
        return false;
    }

    // 检查从2到n-1是否有因数
    for (int i = 2; i < n; i++)
    {
        if (n % i == 0) // 如果能被整除,不是素数
        {
            return false;
        }
    }

    return true;        // 否则是素数
}
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

bool is_prim(int x)  // 判定质数
{
    if (x == 1)  // 1不是质数
    {
        return 0;
    }
    for (int i = 2; i * i <= x; i++)  // 只需要检查到√x
    {
        if (x % i == 0)  // 如果能整除
        {
            return 0;  // 不是质数
        }
    }
    return 1;  // 是质数
}
int main()
{
    int n, x;
    cin >> n;  // 输入数字个数
    for (int i = 0; i < n; i++)  // 处理每个数字
    {
        cin >> x;
        if (is_prim(x))  // 如果是质数
        {
            printf("%d ", x);  // 输出
        }
    }
    return 0;
}
// 使用acwing模板二刷
#include <bits/stdc++.h>
using namespace std;
int n;  // 数字个数

bool is_prime(int n)  // 质数判断函数
{
    if (n < 2)  // 小于2不是质数
    {
        return false;
    }
    for (int i = 2; i <= n / i; i++)  // 优化:检查到√n
    {
        if (n % i == 0)  // 如果能整除
        {
            return false;  // 不是质数
        }
    }
    return true;  // 是质数
}
int main()
{
    cin >> n;  // 输入数字个数
    for (int i = 1; i <= n; i++)  // 读取n个数字
    {
        int x;
        cin >> x;
        if (is_prime(x))  // 如果是质数
        {
            cout << x << " ";  // 输出
        }
    }
    return 0;
}

【运行结果】

5
3 4 5 6 7
3 5 7
posted @ 2026-08-31 09:27  团爸讲算法  阅读(19)  评论(0)    收藏  举报