#include<iostream>
using namespace std;
bool prime(int n){
for(int i = 2;i*i<=n;i++){
if(n%i==0){
return false;
}
}
return true;
}
int main(){
int num;
while(cin>>num){
int sum = 0;
int count=0;
int i = 2;
while(sum<num){
if(prime(i)){
sum+=i;
if(sum<=num){
count++;
cout<<i<<endl;
}
}
i++;
}
cout<<count<<endl;
}
return 0;
}
一、先分析 原代码的 3 个核心问题(必须修复)
✅ 问题 1:质数判断函数prime(n)有逻辑缺陷 & 健壮性不足
- 没有处理
n<=1的情况(虽然主函数i从 2 开始,但函数本身应该具备健壮性); - 对偶数的判断完全冗余:比如判断
9是不是质数,明明可以先判断偶数直接排除,原代码还是会循环i=2,3; i*i <=n存在整型溢出风险:如果n很大(比如接近int最大值),i*i会溢出变成负数,导致判断失效。
✅ 问题 2:主函数累加逻辑 冗余且有瑕疵
原代码逻辑:sum += i 累加质数 → 判断sum<=num → 满足则计数。
问题:如果sum+i已经超过num,依然会执行sum += i,导致 sum 的值是错误的(超出 num),只是后续不计数而已,属于「无效累加」,还多了一层嵌套if判断,代码冗余。
✅ 问题 3:性能极低(最核心)
对每一个数字i都单独调用prime(i)判断是否为质数,这是「暴力判断质数」的典型低效写法:
- 比如判断
100以内的质数,会对2,3,4,...,100逐个做质数判断,每个判断的时间复杂度是O(n); - 整体时间复杂度达到 O(n根号n),当
num较大时(比如num=1e5),运行会明显卡顿。
#include<iostream>
#include<cmath> // 用于sqrt函数
using namespace std;
// 优化后的质数判断函数:高效+健壮+无缺陷
bool prime(int n) {
if (n <= 1) return false; // 1及以下都不是质数
if (n == 2) return true; // 2是唯一的偶质数
if (n % 2 == 0) return false;// 所有偶数直接排除,循环只需要判断奇数,效率翻倍
// 从3开始,只遍历奇数,循环上限用sqrt(n),无溢出风险
for (int i = 3; i <= sqrt(n); i += 2) {
if (n % i == 0) return false;
}
return true;
}
int main(){
int num;
while(cin >> num){
int sum = 0;
int count = 0;
int i = 2;
while(true){
if (prime(i) && (sum + i) <= num) { // 预判累加和,无无效累加,核心优化
sum += i;
count++;
cout << i << endl;
} else if (prime(i) && (sum + i) > num) {
// 质数累加后超界,直接退出循环,无需继续遍历
break;
}
i++;
// 边界保护:当i超过num时,一定超界,退出
if(i > num) break;
}
cout << "质数个数:" << count << endl;
}
return 0;
}
三、版本二:进阶优化版(埃拉托斯特尼筛法,性能暴增 100~1000 倍,强烈推荐)
✅ 核心优化思路:为什么这个版本性能碾压?
你的原代码和基础优化版,本质都是「逐个数字判断是否为质数」,属于暴力枚举;
而埃拉托斯特尼筛法(埃氏筛) 是预处理思想:一次性筛选出 [2, num] 范围内的所有质数,时间复杂度仅为 O(nloglogn),这是质数相关问题的最优解法之一,也是竞赛 / 工程中必用的写法。
✅ 埃氏筛法 核心原理(一句话看懂)
先假设所有数都是质数,然后从最小的质数
2开始,把2的所有倍数标记为「非质数」;再找下一个未被标记的数3,把3的所有倍数标记为非质数;以此类推,最终未被标记的数就是质数。
✅ 适配你的业务逻辑
筛出 [2, num] 内的所有质数 → 从小到大累加这些质数 → 累加和不超过 num 就计数,超过就停止,完美匹配需求。
#include<iostream>
#include<vector>
using namespace std;
int main(){
int num;
while(cin >> num){
if(num < 2){ // 边界判断:小于2的数没有质数
cout << 0 << endl;
continue;
}
// ========== 埃氏筛:一次性筛选出[2,num]的所有质数 ==========
vector<bool> is_prime(num + 1, true); // is_prime[x]表示x是否是质数
is_prime[0] = is_prime[1] = false; // 0和1不是质数
for(int i = 2; i*i <= num; ++i){
if(is_prime[i]){ // 如果i是质数,标记i的所有倍数为非质数
for(int j = i*i; j <= num; j += i){
is_prime[j] = false;
}
}
}
// ========== 你的核心业务逻辑:累加质数+统计个数 ==========
int sum = 0;
int count = 0;
for(int i = 2; i <= num; ++i){
if(is_prime[i]){ // 遍历筛选好的质数
if(sum + i <= num){
sum += i;
count++;
cout << i << endl;
}else{
break; // 累加超界,直接退出
}
}
}
cout << "质数个数:" << count << endl;
}
return 0;
}
一般般