题解:洛谷 P5736 质数筛
【题目来源】
【题目描述】
输入 \(n\) 个不大于 \(10^5\) 的正整数。要求全部储存在数组中,去除掉不是质数的数字,依次输出剩余的质数。
【输入】
第一行输入一个正整数 \(n\),表示整数个数。
第二行输入 \(n\) 个正整数 \(a_i\),以空格隔开。
【输出】
输出一行,依次输出 \(a_i\) 中剩余的质数,以空格隔开。
【输入样例】
5
3 4 5 6 7
【输出】
3 5 7
【核心思想】
-
问题分析:给定 \(n\) 个不大于 \(10^5\) 的正整数,要求筛选出其中的质数并按原顺序输出。这是最基础的质数判定与筛选问题,核心是实现一个高效的质数判断函数,然后遍历数组依次判断。
-
算法选择:
- 试除法判定质数:对于每个数 \(x\),检查从 \(2\) 到 \(\sqrt{x}\) 的所有整数是否能整除 \(x\)。若能整除则不是质数,否则是质数。时间复杂度为 \(O(\sqrt{x})\),对于 \(x \le 10^5\) 完全可行。
- 优化:只需检查到 \(\sqrt{x}\),因为若 \(x\) 有大于 \(\sqrt{x}\) 的因子,则必然有小于 \(\sqrt{x}\) 的对应因子。代码中使用
i <= n / i避免浮点数运算。
-
关键步骤:
- 读入:读取 \(n\),然后循环读取 \(n\) 个整数。
- 质数判断:对每个数调用
is_prime(x):- 若 \(x < 2\),返回
false。 - 从 \(i = 2\) 到 \(i \le x / i\),若 \(x \% i == 0\),返回
false。 - 否则返回
true。
- 若 \(x < 2\),返回
- 输出:若是质数则输出该数,用空格分隔。
-
时间/空间复杂度:
- 时间复杂度:\(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)\),只使用常数空间。
-
质数判定与优化:
- 试除法:最直观的质数判定方法,适合单个数或少量数的判断。
- 边界处理:\(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
浙公网安备 33010602011771号