题解:学而思编程 质数
【题目来源】
学而思编程:质数
【题目描述】
质数是指在大于 \(1\) 的自然数中,除了 \(1\) 和它本身以外不再有其他因数的自然数。现在给定你两个整数 \(a,b\),请你找出 \(a\sim b\) 之间(不包含 \(a,b\))所有个位为 \(1\) 的质数。
【输入】
一行两个整数 \(a,b\)。
【输出】
从小到大输出所有满足条件的质数,质数之间单个空格隔开,如果没有符合条件的质数输出 \(-1\)。
【输入样例】
1 97
【输出样例】
11 31 41 61 71
【核心思想】
-
问题分析:给定区间 \((a, b)\),找出其中所有个位为 \(1\) 的质数。这是一个范围筛选 + 质数判定问题,关键在于利用个位约束减少待检查的数字数量,仅对个位为 \(1\) 的数进行质数判定。
-
算法选择:
- 个位筛选:只检查个位为 \(1\) 的数字,步长为 \(10\)
- 试除法质数判定:对每个候选数,检查 \(2\) 到 \(\sqrt{n}\) 是否有因数
- 边界调整:将 \(a\) 向上调整到最近的 \(10\) 的倍数,确保从个位为 \(1\) 的数开始检查
-
关键步骤:
-
初始化:读取 \(a\) 和 \(b\)
-
边界调整:
- 若
a % 10 != 0:a = (a / 10 + 1) * 10:将 \(a\) 向上取整到最近的 \(10\) 的倍数
- 若
-
筛选检查:
flag = 0:标记是否找到符合条件的质数- 遍历 \(i\) 从
a + 1到b - 1,步长 \(10\):- 若
isp(i)为真:- 输出 \(i\)
flag = 1
- 若
-
无解处理:
- 若
flag == 0:输出 \(-1\)
- 若
-
质数判定函数
isp(n):- 若
n < 2:返回false - 遍历 \(i\) 从 \(2\) 到 \(\sqrt{n}\):
- 若
n % i == 0:返回false
- 若
- 返回
true
- 若
-
-
时间/空间复杂度:
- 时间复杂度:\(O(\frac{b-a}{10} \times \sqrt{b})\),仅检查约 \(\frac{b-a}{10}\) 个候选数
- 空间复杂度:\(O(1)\),仅需常数变量
-
个位筛选的核心思想:
- 步长优化:个位为 \(1\) 的数间隔为 \(10\),用步长 \(10\) 遍历可将候选数减少 \(90\%\)
- 边界对齐:将 \(a\) 调整到 \(10\) 的倍数后,
a + 1即为第一个个位为 \(1\) 的数,确保不遗漏 - 开区间处理:循环条件
i < b严格满足"不包含 \(b\)"的要求 - 提前过滤:在质数判定前先用个位条件过滤,避免大量无效计算
- 适用于"数位约束 + 质数筛选"类问题,利用数位规律大幅减少搜索空间
【算法标签】
质数
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int a, b; // 输入的区间边界[a, b]
bool flag; // 标记是否找到了符合条件的素数
// 判断一个数是否为素数
bool isp(int n)
{
if (n < 2) // 小于2的数不是素数
{
return false;
}
// 检查从2到√n的所有数
for (int i = 2; i * i <= n; i++)
{
if (n % i == 0) // 如果能被整除,不是素数
{
return false;
}
}
return true; // 是素数
}
int main()
{
cin >> a >> b; // 输入区间边界
// 调整a为10的倍数(向上取整到最近的10的倍数)
if (a % 10 != 0)
{
a = (a / 10 + 1) * 10;
}
// 在区间(a, b)内查找以1结尾的素数
for (int i = a + 1; i < b; i += 10)
{
if (isp(i)) // 如果是素数
{
cout << i << " "; // 输出这个素数
flag = 1; // 标记找到了素数
}
}
// 如果没有找到符合条件的素数
if (flag == 0)
{
cout << "-1"; // 输出-1
}
return 0; // 程序正常结束
}
【运行结果】
1 97
11 31 41 61 71
浙公网安备 33010602011771号