题解:洛谷 P5723 质数口袋
【题目来源】
【题目描述】
小 A 有一个质数口袋,里面可以装各个质数。他从 \(2\) 开始,依次判断各个自然数是不是质数,如果是质数就会把这个数字装入口袋。
口袋的负载量就是口袋里的所有数字之和。
但是口袋的承重量有限,装的质数的和不能超过 \(L\)。给出 \(L\),请问口袋里能装下几个质数?将这些质数从小往大输出,然后输出最多能装下的质数的个数,数字之间用换行隔开。
【输入】
一行一个正整数 \(L\)。
【输出】
将这些质数从小往大输出,然后输出最多能装下的质数个数,所有数字之间有一空行。
【输入样例】
100
【输出样例】
2
3
5
7
11
13
17
19
23
9
【核心思想】
-
问题分析:给定容量上限 \(L\),从 \(2\) 开始依次判断自然数是否为质数,将质数装入"口袋"(累加和),直到下一个质数会使总和超过 \(L\) 时停止。输出所有装入的质数和质数个数。
-
算法选择:
- 试除法判质:对每个数 \(i\),用 \(2 \sim i-1\) 试除判断是否为质数
- 贪心装入:按从小到大顺序,能装就装,直到超出容量
-
关键步骤:
- 读入数据:
cin >> l - 初始化:
sum = 0(质数个数),tot = 0(质数和) - 遍历自然数(\(i\) 从 \(2\) 开始,条件
tot + i <= l):- 判质:
mark = 0,内层 \(j\) 从 \(2\) 到 \(i-1\),若i % j == 0则mark = 1(非质数) - 若
mark == 0(是质数):- 若
i + tot <= l:输出 \(i\),tot += i,sum++ - 否则
break(超出容量)
- 若
- 判质:
- 输出个数:
sum
- 读入数据:
-
时间/空间复杂度:
- 时间复杂度:\(O(m^2)\),\(m\) 为装入的质数个数,每个质数判断需 \(O(i)\) 次试除
- 空间复杂度:\(O(1)\),无需存储所有质数,边判边输出
-
贪心装入的核心思想:
- 从小到大顺序:从 2 开始依次尝试,保证质数按升序输出
- 即时输出:判定为质数且能装入时立即输出,无需存储
- 容量预判:外层循环条件
tot + i <= l提前终止不可能的情况 - 试除法简单性:数据范围小,试除法足够高效,无需埃氏筛或线性筛
- 适用于质数判定、贪心选择、容量限制类入门问题
【算法标签】
普及- #质数
【代码详解】
#include <bits/stdc++.h> // 包含标准库头文件(万能头文件)
using namespace std; // 使用标准命名空间
/**
* 主函数 - 程序入口
* @return 程序执行状态码(0表示成功)
*/
int main()
{
int l; // 定义变量:质数口袋的最大容量
int sum = 0; // 定义变量:质数口袋中质数的个数
int tot = 0; // 定义变量:质数口袋中质数的总和
cin >> l; // 输入质数口袋的容量
// 遍历从2开始的整数,寻找质数
for (int i = 2; tot + i <= l; i++)
{
// 判断当前数i是否为质数
int mark = 0; // 标记是否为质数(0表示是质数)
for (int j = 2; j < i; j++)
{
if (i % j == 0)
{
mark = 1; // 发现能整除的数,不是质数
break;
}
}
// 如果是质数
if (mark == 0)
{
// 检查是否能放入质数口袋
if (i + tot <= l)
{
cout << i << endl; // 输出当前质数
tot += i; // 更新质数总和
sum++; // 更新质数个数
}
else
{
break; // 超过容量,终止循环
}
}
}
// 输出质数口袋中质数的总个数
cout << sum;
return 0; // 程序正常结束
}
【运行结果】
100
2
3
5
7
11
13
17
19
23
9
浙公网安备 33010602011771号