7 多层循环结构(二)循环嵌套综合应用

正在加载视频播放器…

GESP C++ 二级:多层循环结构(二)循环嵌套综合应用

核心目标:在掌握嵌套 for 循环的基础上,综合运用多层循环与分支、数位拆分、数学函数,解决枚举、图形打印、数学统计、数位处理等综合问题。
外层控制主变量,内层控制次变量;循环负责遍历,分支负责筛选;累加计数变量位置要正确,break/continue 只作用于当前层。

一、综合应用核心思想

循环嵌套综合题,通常由以下要素组合而成:

要素 作用 示例
外层循环 控制主要变量,如行、枚举的第一个数 for (int i = 1; i <= n; i++)
内层循环 控制次要变量,如列、枚举的第二个数 for (int j = 1; j <= m; j++)
分支判断 筛选满足条件的组合或控制图形 if (i + j == 50)
累加/计数 统计满足条件的个数或求和 cnt++、sum += ...
数位拆分 处理整数的每一位 n % 10、n / 10
数学函数 辅助计算 sqrt、abs、pow

综合题解题步骤:

  1. 确定需要枚举哪些变量。
  2. 确定每个变量的范围。
  3. 确定循环嵌套层次。
  4. 在内层写条件判断。
  5. 在合适位置累加、计数或输出。
  6. 检查边界、初始化和输出格式。

二、循环嵌套与分支结合

1. 筛选满足条件的数

例:输出 1~100 中能被 3 整除且能被 5 整除的数。

for (int i = 1; i <= 100; i++) {
    if (i % 3 == 0 && i % 5 == 0) {
        cout << i << " ";
    }
}

输出:

15 30 45 60 75 90

2. 双层循环筛选组合

例:求 1~9 中,两个数之和为 10 的组合。

for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= 9; j++) {
        if (i + j == 10) {
            cout << i << "+" << j << "=10" << endl;
        }
    }
}

3. 计数

例:统计 1~100 中有多少对数 (i, j) 满足 i + j = 50 且 i < j。

int cnt = 0;
for (int i = 1; i <= 100; i++) {
    for (int j = 1; j <= 100; j++) {
        if (i + j == 50 && i < j) {
            cnt++;
        }
    }
}
cout << cnt << endl;

4. 累加

例:求 1~n 中所有偶数的和。

int sum = 0;
for (int i = 1; i <= n; i++) {
    if (i % 2 == 0) {
        sum += i;
    }
}
cout << sum << endl;

重点:sum 和 cnt 必须定义在循环外,循环内只更新。

三、枚举法(穷举法)

枚举法就是把所有可能的情况一一列举出来,用条件筛选出正确答案。

1. 百钱百鸡

公鸡 5 元一只,母鸡 3 元一只,小鸡 1 元三只。100 元买 100 只鸡,求所有方案。

for (int x = 0; x <= 20; x++) {          // 公鸡最多 20 只
    for (int y = 0; y <= 33; y++) {      // 母鸡最多 33 只
        int z = 100 - x - y;             // 小鸡数量
        if (z >= 0 && 5 * x + 3 * y + z / 3 == 100 && z % 3 == 0) {
            cout << x << " " << y << " " << z << endl;
        }
    }
}

输出:

0 25 75
4 18 78
8 11 81
12 4 84

2. 鸡兔同笼

头共 h 个,脚共 f 只,求鸡和兔各多少。

for (int chicken = 0; chicken <= h; chicken++) {
    int rabbit = h - chicken;
    if (2 * chicken + 4 * rabbit == f) {
        cout << chicken << " " << rabbit << endl;
    }
}

3. 水仙花数

三位数,各位数字立方和等于本身。

for (int n = 100; n <= 999; n++) {
    int a = n / 100;
    int b = n / 10 % 10;
    int c = n % 10;
    if (a*a*a + b*b*b + c*c*c == n) {
        cout << n << " ";
    }
}

输出:

153 370 371 407

4. 完数

一个数等于它的所有真因子之和,如 6 = 1+2+3。

for (int n = 2; n <= 1000; n++) {
    int sum = 0;
    for (int i = 1; i < n; i++) {
        if (n % i == 0) {
            sum += i;
        }
    }
    if (sum == n) {
        cout << n << " ";
    }
}

输出:

6 28 496

四、图形打印进阶

1. 空心矩形

输入 n 行 m 列,边界打印 *,内部打印空格。

for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
        if (i == 1 || i == n || j == 1 || j == m) {
            cout << "*";
        } else {
            cout << " ";
        }
    }
    cout << endl;
}

输入 4 6,输出:

******
*    *
*    *
******

2. 等腰三角形

for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n - i; j++) cout << " ";
    for (int j = 1; j <= 2 * i - 1; j++) cout << "*";
    cout << endl;
}

输入 4,输出:

   *
  ***
 *****
*******

3. 菱形

int n;
cin >> n;

// 上半部分
for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n - i; j++) cout << " ";
    for (int j = 1; j <= 2 * i - 1; j++) cout << "*";
    cout << endl;
}
// 下半部分
for (int i = n - 1; i >= 1; i--) {
    for (int j = 1; j <= n - i; j++) cout << " ";
    for (int j = 1; j <= 2 * i - 1; j++) cout << "*";
    cout << endl;
}

输入 4,输出:

   *
  ***
 *****
*******
 *****
  ***
   *

4. 数字金字塔

for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n - i; j++) cout << " ";
    for (int j = 1; j <= i; j++) cout << j;
    for (int j = i - 1; j >= 1; j--) cout << j;
    cout << endl;
}

输入 4,输出:

   1
  121
 12321
1234321

5. 九九乘法表

for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= i; j++) {
        cout << j << "*" << i << "=" << i * j << " ";
    }
    cout << endl;
}

五、数学问题综合

1. 求 1~n 中所有素数

for (int i = 2; i <= n; i++) {
    bool isPrime = true;
    for (int j = 2; j * j <= i; j++) {
        if (i % j == 0) {
            isPrime = false;
            break;
        }
    }
    if (isPrime) {
        cout << i << " ";
    }
}

2. 求 1! + 2! + ... + n!

long long sum = 0;
for (int i = 1; i <= n; i++) {
    long long fac = 1;
    for (int j = 1; j <= i; j++) {
        fac *= j;
    }
    sum += fac;
}
cout << sum << endl;

3. 求最大公约数(辗转相除法)

int a, b;
cin >> a >> b;
while (b != 0) {
    int t = a % b;
    a = b;
    b = t;
}
cout << a << endl;

4. 求最小公倍数

int lcm = a * b / gcd(a, b);

5. 统计 1~n 中数字 k 出现的次数

int cnt = 0;
for (int i = 1; i <= n; i++) {
    int t = i;
    while (t > 0) {
        if (t % 10 == k) cnt++;
        t /= 10;
    }
}
cout << cnt << endl;

六、数位拆分与循环嵌套

1. 求所有数位和为指定值的数

for (int i = 1; i <= 1000; i++) {
    int t = i, sum = 0;
    while (t > 0) {
        sum += t % 10;
        t /= 10;
    }
    if (sum == 9) {
        cout << i << " ";
    }
}

2. 数字反转后相加

int n;
cin >> n;
int t = n, rev = 0;
while (t > 0) {
    rev = rev * 10 + t % 10;
    t /= 10;
}
cout << n + rev << endl;

3. 回文数判断

int t = n, rev = 0;
while (t > 0) {
    rev = rev * 10 + t % 10;
    t /= 10;
}
if (rev == n) cout << "回文数";
else cout << "不是回文数";

七、常见综合模型与模板

模型 核心代码模板
双层枚举 for (i...) for (j...) if (条件) ...
计数 cnt = 0; ... if (条件) cnt++;
累加 sum = 0; ... sum += ...;
求素数 外层遍历,内层 2 ~ sqrt(i) 判断
完数 外层遍历,内层求因子和
水仙花数 外层 100~999,数位拆分
百钱百鸡 双层枚举,第三量由总数推出
鸡兔同笼 枚举鸡,兔由头数推出
图形打印 外层行,内层列;空格 + 星号
数字三角形 内层 j <= i
菱形 上半 + 下半,空格递减/递增
数位统计 外层遍历,内层 while (t > 0)
最大公约数 while (b != 0) 辗转相除

八、易错点

  1. 累加/计数变量初始化位置错误

    for (...) {
        int sum = 0;   // 错误:每次循环都清零
    }
    

    应定义在循环外。

  2. 循环变量重名

    for (int i = 1; i <= n; i++)
        for (int i = 1; i <= m; i++)   // 错误
    
  3. break 只跳出内层
    需要跳出多层时用标志变量。

  4. continue 跳过更新导致死循环

    while (i < n) {
        if (条件) continue;
        i++;
    }
    
  5. 循环边界错误
    i < n 与 i <= n 结果不同。

  6. 整数除法丢小数

    double avg = sum / n;   // 错误,应 1.0 * sum / n
    
  7. 数位拆分忘记特判 0
    0 的位数是 1。

  8. 图形打印换行位置错误
    换行放在内层循环结束后、外层循环内。

  9. 输出格式错误
    注意空格、换行,严格按题目要求。

  10. 溢出
    大数用 long long,乘法可写 1LL * a * b。

  11. 浮点数比较
    不要直接用 ==。

  12. 死循环
    循环变量未更新或条件永远为真。

九、阅读程序写结果

题目 1

int cnt = 0;
for (int i = 1; i <= 5; i++) {
    for (int j = 1; j <= 5; j++) {
        if (i + j == 6) cnt++;
    }
}
cout << cnt << endl;

输出:

5

题目 2

for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= i; j++) {
        cout << j;
    }
    cout << endl;
}

输出:

1
12
123
1234

题目 3

int sum = 0;
for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
        sum += i * j;
    }
}
cout << sum << endl;

输出:

36

题目 4

for (int i = 1; i <= 5; i++) {
    for (int j = 1; j <= 5; j++) {
        if (j == 3) break;
        cout << i << j << " ";
    }
    cout << endl;
}

输出:

11 12 
21 22 
31 32 
41 42 
51 52 

题目 5

for (int n = 100; n <= 999; n++) {
    int a = n / 100;
    int b = n / 10 % 10;
    int c = n % 10;
    if (a*a*a + b*b*b + c*c*c == n) {
        cout << n << " ";
    }
}

输出:

153 370 371 407

十、编程题示例

1. 输出 1~n 中所有素数

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    for (int i = 2; i <= n; i++) {
        bool isPrime = true;
        for (int j = 2; j * j <= i; j++) {
            if (i % j == 0) {
                isPrime = false;
                break;
            }
        }
        if (isPrime) cout << i << " ";
    }
    return 0;
}

2. 百钱百鸡

#include <iostream>
using namespace std;

int main() {
    for (int x = 0; x <= 20; x++) {
        for (int y = 0; y <= 33; y++) {
            int z = 100 - x - y;
            if (z >= 0 && 5 * x + 3 * y + z / 3 == 100 && z % 3 == 0) {
                cout << x << " " << y << " " << z << endl;
            }
        }
    }
    return 0;
}

3. 打印菱形

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n - i; j++) cout << " ";
        for (int j = 1; j <= 2 * i - 1; j++) cout << "*";
        cout << endl;
    }
    for (int i = n - 1; i >= 1; i--) {
        for (int j = 1; j <= n - i; j++) cout << " ";
        for (int j = 1; j <= 2 * i - 1; j++) cout << "*";
        cout << endl;
    }
    return 0;
}

4. 统计 1~n 中数字 k 出现次数

#include <iostream>
using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        int t = i;
        while (t > 0) {
            if (t % 10 == k) cnt++;
            t /= 10;
        }
    }
    cout << cnt << endl;
    return 0;
}

十一、速查表

需求 写法
双层枚举 for (i...) for (j...) if (条件) ...
计数 cnt = 0; ... if (条件) cnt++;
累加 sum = 0; ... sum += ...;
求素数 外层遍历,内层 2 ~ sqrt(i)
完数 外层遍历,内层求因子和
水仙花数 100~999,数位拆分
百钱百鸡 双层枚举,第三量推出
鸡兔同笼 枚举鸡,兔由头数推出
空心矩形 边界判断 i==1 || i==n || j==1 || j==m
等腰三角形 空格 n-i,星号 2*i-1
菱形 上半 + 下半
数字金字塔 空格 + 升序 + 降序
数位统计 外层遍历,内层 while (t > 0)
最大公约数 while (b != 0) 辗转相除
跳出内层 break
跳过本次 continue
跳出多层 标志变量

十二、总结

循环嵌套综合应用是 GESP 二级的核心难点。

  1. 外层控制主变量,内层控制次变量。
  2. 循环负责遍历,分支负责筛选。
  3. 枚举法就是列举所有可能,用条件筛选。
  4. 累加变量初始化为 0,累乘变量初始化为 1。
  5. 计数和累加变量必须定义在循环外。
  6. break 只跳出当前层,continue 只跳过当前层本次。
  7. 图形打印注意空格、星号、换行位置。
  8. 数位拆分用 % 10 和 / 10,注意特判 0。
  9. 大数用 long long,防止溢出。
  10. 输出格式严格按题目要求,不多空格、不多换行。

复习建议:多练“阅读程序写结果”“图形打印”“枚举法”“数位统计”四类题,重点注意循环边界、变量初始化、break/continue 作用范围、整数除法和输出格式。考试中先确定枚举变量和范围,再写循环和条件,最后逐行模拟验证。