202406-小杨的幸运数字(luogu-P10720)
GESP C++ 2024年6月五级真题,数论-素数思想考点,难度⭐⭐★☆☆,属于五级真题中比较简单的。洛谷难度等级普及−
luogu-P10720 [GESP202406 五级] 小杨的幸运数字
题目要求
题目描述
小杨认为他的幸运数字应该恰好有两种不同的质因子,例如, 的质因子有 ,恰好为两种不同的质因子,因此 是幸运数字,而 的质因子有 ,不符合要求,不为幸运数字。
小杨现在有 个正整数,他想知道每个正整数是否是他的幸运数字。
输入格式
第一行包含一个正整数 ,代表正整数个数。
之后 行,每行一个正整数。
输出格式
输出 行,对于每个正整数,如果是幸运数字,输出 ,否则输出 。
输入输出样例 #1
输入 #1
3
7
12
30输出 #1
0
1
0说明/提示
样例解释
的质因子有 ,只有一种。
的质因子有 ,恰好有两种。
的质因子有 ,有三种。
数据范围
| 子任务编号 | 数据点占比 | 正整数值域 | |
|---|---|---|---|
对于全部数据,保证有 ,每个正整数 满足 。
题目分析
解题思路
- 读入 与 个正整数。
- 对每个数 :
- 初始化计数器
count = 0。 - 从 开始试除到 :
– 若 ,说明 是一个新质因子,count++。
– 把 中所有 因子全部除掉,避免重复。
– 一旦count > 2立即break,提前剪枝。 - 若最终剩余 ,则剩余部分本身也是质因子,
count++。
- 初始化计数器
- 判断
count == 2输出 ,否则输出 。
复杂度
单次分解最坏 , 时总运算量约 级,可轻松通过。
空间仅若干变量,。
该做法代码极短,无需预处理,在五级数据范围内已足够高效;若值域再大,可改为“埃氏筛+质数表试除”进一步加速(不做展开,详见示例代码)。
示例代码
方法一、直接法
#include <iostream>
#include <cmath>
int main() {
int n;
std::cin >> n; // 读入待检测的正整数个数
for (int i = 0; i < n; i++) {
int a;
std::cin >> a; // 读入当前待检测的正整数
int count = 0; // 记录不同质因子的个数
// 试除法枚举可能的质因子,只需到 sqrt(a)
for (int j = 2; j <= sqrt(a); j++) {
if (a % j == 0) { // j 是 a 的一个质因子
count++; // 发现新的质因子
}
// 将 a 中所有 j 因子全部除掉,避免重复计数
while (a % j == 0) {
a /= j;
}
// 提前退出:已经超过两种质因子,必定不是幸运数字
if (count > 2) {
break;
}
}
// 若剩余 a>1,则剩下的 a 本身也是一个质因子
if (a > 1) {
count++;
}
// 恰好两种不同质因子则输出 1,否则输出 0
std::cout << (count == 2 ? 1 : 0) << std::endl;
}
return 0;
}方法二、线性筛法(相对复杂)
#include <iostream>
#include <vector>
// 标记数组:is_primes[i]==0 表示 i 是质数;==1 表示合数
int is_primes[1000005];
// 线性筛得到的质数表,后续用于试除
std::vector<int> prime_nums;
int main() {
int n;
std::cin >> n;
// 0 和 1 不是质数,先标记
is_primes[0] = is_primes[1] = 1;
// 线性筛(欧拉筛)预处理 1~1e6 的质数
for (int i = 2; i <= 1000000; i++) {
if (is_primes[i] == 0) { // i 是质数,加入质数表
prime_nums.push_back(i);
}
// 用当前质数表筛掉合数
for (int num : prime_nums) {
long long x = 1LL * i * num; // 计算合数
if (x > 1000000) {
break; // 超出范围,退出
}
is_primes[x] = 1; // 标记为合数
if (i % num == 0) {
break; // 保证每个合数只被最小质因子筛一次
}
}
}
// 处理每个询问
for (int i = 0; i < n; i++) {
int a;
std::cin >> a;
int count = 0; // 记录不同质因子个数
// 用质数表试除,统计不同质因子
for (int j = 0; j < prime_nums.size(); j++) {
if (a % prime_nums[j] == 0) { // 发现质因子
count++;
}
if (count > 2) { // 提前剪枝
break;
}
}
// 恰好两种质因子输出 1,否则 0
std::cout << (count == 2 ? 1 : 0) << std::endl;
}
return 0;
}
}本文由coderli.com原创,按照CC BY-NC-SA 4.0 进行授权
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
“luogu-”系列题目可在 洛谷题库 在线评测。
“bcqm-”系列题目可在 编程启蒙题库 在线评测。
GESP/CSP认证交流QQ群: 688906745
GESP/CSP 认证学习微信公众号

最后更新于