返回 课程

信奥AC之路-2级

0% 完成
0/0 步骤
  1. 第一课:字符
    5 主题|小节
  2. 第二课 嵌套循环与矩形图案(一)
    4 主题|小节
  3. 第三课 嵌套循环与矩形图案(二)
    3 主题|小节
  4. 第四课:矩形三
    5 主题|小节
  5. 第五课:字符矩形
    7 主题|小节
  6. 第六课:直角三角形
    6 主题|小节
  7. 第七课:倒三角形
    7 主题|小节
  8. 第八课:字符三角形
    8 主题|小节
  9. 第九课:字符倒三角形
    7 主题|小节
  10. 第十课:平行四边形
    6 主题|小节
  11. 第十一课:字符直角三角形
    5 主题|小节
  12. 第十二课:左斜三角形
    6 主题|小节
  13. 第十三课:等腰三角形
    6 主题|小节
  14. 第十四课:倒置等腰三角形
    7 主题|小节
  15. 第十五课:上下对称图形
    4 主题|小节
  16. 第十六课:复杂对称图形
    5 主题|小节
  17. 第十七课:左右对称图形
    5 主题|小节
  18. 第十八课:空心图形
    5 主题|小节
  19. 第十九课:空心图形
    3 主题|小节
  20. 第二十课:嵌套应用
    4 主题|小节
  21. 第二十一课:嵌套应用二
    4 主题|小节
  22. 第二十二课:嵌套应用三
    3 主题|小节
  23. 第二十三课:嵌套应用四
    3 主题|小节
课 20, 主题|小节 3
进行中

20.3 嵌套循环与数论问题

2026年1月15日
课 进展
0% 完成

“数论问题常常需要我们检查数字的特殊性质,”我解释道,”比如质数判定、回文数判断等,这些都可以通过嵌套循环来实现。”

20.3.1 统计质数

题目描述:统计a~b(1≤a<b≤100,000)之间有多少质数。

样例输入

10 20

样例输出

4

代码实现

#include <iostream>
using namespace std;

int main() {
    int a, b, cnt=0;  // a和b是范围边界,cnt用于计数质数个数
    bool f;           // 布尔变量f用来标记当前数是否为质数
    cin >> a >> b;    // 读入范围边界
    
    // 外循环:遍历a到b的每个数
    for(int i=a; i<=b; i++) {
        f = true;     // 初始假设i是质数
        
        // 特殊情况处理:小于2的数不是质数
        if(i < 2) f = false;
        
        // 内循环:检查i是否能被2到sqrt(i)的数整除
        // 只需检查到sqrt(i),因为如果i不是质数,至少有一个因子小于等于sqrt(i)
        for(int j=2; j*j<=i; j++) {
            if(i % j == 0) {  // 如果i能被j整除
                f = false;    // 则i不是质数
                break;        // 找到一个因子就可以确定非质数,立即退出循环
            }
        }
        
        // 如果i是质数,计数器加1
        if(f) cnt++;
    }
    cout << cnt;  // 输出质数总数
    return 0;
}

思考

  • 外循环(i)遍历从a到b的每个数
  • 内循环(j)检查i是否能被2到sqrt(i)的任何数整除
  • 使用布尔变量f标记当前数是否为质数
  • 优化:只需要检查到sqrt(i),如果i有约数,其中一个一定小于等于sqrt(i)
  • 进一步优化:使用break提前结束内循环,一旦发现i不是质数

20.3.2 统计回文数

题目描述:统计a~b(1≤a<b≤100,000)之间回文数的个数。回文数是指从左向右读和从右向左读都一样的数,如121、1221等。

样例输入

10 100

样例输出

9

代码实现

#include <iostream>
using namespace std;

int main() {
    int a, b, cnt=0;  // a和b是范围边界,cnt用于计数回文数个数
    cin >> a >> b;    // 读入范围边界
    
    // 外循环:遍历a到b的每个数
    for(int i=a; i<=b; i++) {
        int x = i, m = 0;  // x保存原始数值,m用于存储反转后的数
        
        // 内部while循环:将数字x反转,结果存储在m中
        while(x) {
            m = m*10 + x%10;  // 取x的末位数字,加到m的末尾
            x /= 10;          // 去掉x的末位数字
        }
        
        // 如果反转后的数等于原数,则为回文数
        if(m == i) cnt++;
    }
    cout << cnt;  // 输出回文数总数
    return 0;
}

思考

  • 外循环(i)遍历从a到b的每个数
  • 内部使用while循环将数字反转,得到m
  • 判断反转后的数m是否等于原数i
  • 这个实验展示了在一个循环内使用另一种循环(while循环)的灵活性

20.3.3 回文质数

题目描述:回文质数是既是质数又是回文数的数,如151、131等。写一个程序找出范围(5≤a<b≤100,000)间的所有回文质数。

样例输入

100 200

样例输出

101
131
151
181
191

代码实现

#include <iostream>
using namespace std;

int main() {
    int a, b;
    cin >> a >> b;  // 读入范围边界
    
    // 外循环:遍历a到b的每个数
    for(int i=a; i<=b; i++) {
        bool f = true;  // 布尔变量f用来标记当前数是否为质数,初始假设为质数
        
        // 第一步:判断是否为质数
        if(i < 2) f = false;  // 小于2的数不是质数
        
        // 内循环:检查i是否能被2到sqrt(i)的数整除
        for(int j=2; j*j<=i; j++) {
            if(i % j == 0) {  // 如果i能被j整除
                f = false;    // 则i不是质数
                break;        // 找到一个因子就可以确定非质数,立即退出循环
            }
        }
        
        // 如果不是质数,跳过后续判断,继续下一个数
        if(f == false) continue;
        
        // 第二步:判断是否为回文数
        int x = i, m = 0;  // x保存原始数值,m用于存储反转后的数
        
        // 内部while循环:将数字x反转,结果存储在m中
        while(x) {
            m = m*10 + x%10;  // 取x的末位数字,加到m的末尾
            x /= 10;          // 去掉x的末位数字
        }
        
        // 如果是回文数(且前面已确认是质数),则输出
        if(m == i) cout << i << endl;
    }
    return 0;
}

思考

  • 这个实验结合了前两个实验的技巧
  • 先判断数字是否为质数,如果不是则使用continue跳过后续步骤
  • 再判断数字是否为回文数
  • 这是一个很好的例子,展示了如何组合多种条件来解决复杂问题