《循环嵌套强化》学习笔记
------彭彭老师
一、循环嵌套核心思维
"循环嵌套就像俄罗斯套娃"
- 外层循环:控制"大事情"(比如从第1天到第10天)
- 内层循环:控制"小事情"(比如每天要做3次练习)
- 关键规则 :外层每走1步,内层要从头到尾完整走一遍
简单例子:
cpp
// 假设有3天,每天做2次计算
for(int day=1; day<=3; day++){ // 外层:第几天
cout << "第" << day << "天:" << endl;
for(int count=1; count<=2; count++){ // 内层:每天几次
cout << " 第" << count << "次计算" << endl;
}
}
输出:
第1天:
第1次计算
第2次计算
第2天:
第1次计算
第2次计算
第3天:
第1次计算
第2次计算
二、题目详解(信奥一本通)
1091:求阶乘的和
问题:计算 1! + 2! + 3! + ... + n!
通俗解释
想象你要算:
- 1的阶乘(1! = 1)
- 2的阶乘(2! = 1×2 = 2)
- 3的阶乘(3! = 1×2×3 = 6)
- ...
然后把它们加起来!
知识点
- 外层循环:控制要算到哪个数的阶乘(从1到n)
- 内层循环:计算每个数的阶乘(从1乘到这个数本身)
- 累加器:把每个阶乘的结果加起来
简化代码
cpp
#include <iostream>
using namespace std;
int main(){
int n = 5; // 假设n=5
long long sum = 0; // 用来存总和
for(int i=1; i<=n; i++){ // 外层:算第i个数的阶乘
long long fact = 1; // 用来存i的阶乘
for(int j=1; j<=i; j++){ // 内层:计算i!
fact = fact * j; // 1×2×3×...×i
}
sum = sum + fact; // 把阶乘加到总和中
}
cout << "1!+2!+...+n! = " << sum << endl;
return 0;
}
答案示例
- n=3时:1! + 2! + 3! = 1 + 2 + 6 = 9
- n=5时:1 + 2 + 6 + 24 + 120 = 153
1092:求出e的值
问题:计算 e = 1 + 1/1! + 1/2! + 1/3! + ... + 1/n!
通俗解释
这是数学常数e的近似值:
- 先算1(固定)
- 再加 1÷1!
- 再加 1÷2!
- 再加 1÷3!
- ...
知识点
- 双重循环嵌套:外层控制项数,内层计算阶乘
- 除法运算:1除以阶乘
- 精度问题:用double类型
简化代码
cpp
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int n = 10;
double e = 1.0; // 从1开始
for(int i=1; i<=n; i++){ // 外层:加到第i项
long long fact = 1;
for(int j=1; j<=i; j++){ // 内层:计算i!
fact = fact * j;
}
e = e + 1.0 / fact; // 加上1÷i!
}
cout << fixed << setprecision(10) << e << endl;
return 0;
}
答案示例
- n=10时:e ≈ 2.7182818011
- n越大,值越接近真正的e(≈2.718281828459)
1093:计算多项式的值
问题:计算 S = x - x²/2! + x³/3! - x⁴/4! + ...(正负交替)
通俗解释
像坐跷跷板一样,一会加一会减:
- 先加 x
- 再减 x²÷2!
- 再加 x³÷3!
- 再减 x⁴÷4!
- ...
知识点
- 符号交替:用变量控制正负号
- 幂运算:x的i次方
- 组合运算:幂运算和阶乘一起算
简化代码
cpp
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double x = 1.0;
int n = 5;
double sum = 0;
int sign = 1; // 控制正负号:1表示正,-1表示负
for(int i=1; i<=n; i++){
// 计算x的i次方
double power = 1;
for(int j=1; j<=i; j++){
power = power * x;
}
// 计算i的阶乘
long long fact = 1;
for(int k=1; k<=i; k++){
fact = fact * k;
}
// 加上或减去这一项
sum = sum + sign * power / fact;
sign = -sign; // 下一次符号取反
}
cout << "多项式的值 = " << sum << endl;
return 0;
}
答案示例
- x=1, n=5时:1 - 1/2 + 1/6 - 1/24 + 1/120 ≈ 0.633333
1094:与7无关的数
问题:找出1到n中所有与7无关的数
- 不能是7的倍数
- 数字中不能包含7
通俗解释
"与7无关"就是:
- 不能是7的亲戚:不能被7整除(比如14是7×2,不行)
- 名字里不能有7:数字里不能出现7(比如17、27、70都不行)
知识点
- 数字分解:如何判断一个数是否包含数字7
- 整除判断:用%运算符
- 双重条件:两个条件都要满足
简化代码
cpp
#include <iostream>
using namespace std;
int main(){
int n = 30;
int sum = 0;
for(int i=1; i<=n; i++){ // 外层:检查每个数
bool hasSeven = false; // 假设没有7
// 检查是否包含数字7
int num = i;
while(num > 0){
if(num % 10 == 7){ // 个位是7吗?
hasSeven = true;
break;
}
num = num / 10; // 去掉个位,继续检查
}
// 两个条件判断
if(i % 7 != 0 && !hasSeven){
sum = sum + i * i; // 平方和
}
}
cout << "与7无关的数的平方和 = " << sum << endl;
return 0;
}
答案示例
n=30时,与7无关的数有:
1,2,3,4,5,6,8,9,10,11,12,13,15,16,18,19,20,22,23,24,25,26,29,30
平方和 = 17267
1095:数1的个数
问题:统计1到n中,数字1一共出现了多少次
通俗解释
就像数数游戏:
- 从1数到n
- 每看到一个"1"就记下来
- 比如13:有1个1(在数字1中)和1个1(在数字11中)...
知识点
- 数字逐位检查:把每个数拆成个位、十位、百位...
- 计数器:统计1出现的次数
- 嵌套循环:外层遍历数字,内层检查每位
简化代码
cpp
#include <iostream>
using namespace std;
int main(){
int n = 15;
int count = 0; // 统计1的个数
for(int i=1; i<=n; i++){ // 外层:检查每个数
int num = i;
while(num > 0){ // 内层:检查这个数的每一位
if(num % 10 == 1){ // 个位是1吗?
count++;
}
num = num / 10; // 去掉个位
}
}
cout << "1到" << n << "中,1出现了" << count << "次" << endl;
return 0;
}
答案示例
- n=13时:1出现了6 次
(1,10,11,12,13中的1:1有1个,10有1个,11有2个,12有1个,13有1个) - n=20时:1出现了12次
1096:数字统计
问题:统计区间[L,R]中,数字2出现了多少次
通俗解释
和数1的个数类似,但是:
- 区间可以任意:从L到R,不一定要从1开始
- 数字可以任意:统计的是2,不是1
知识点
- 区间遍历:从L到R循环
- 通用统计:可以统计任意数字
- 函数思维:相似的代码结构
简化代码
cpp
#include <iostream>
using namespace std;
int main(){
int L = 2, R = 22;
int digit = 2; // 要统计的数字
int count = 0;
for(int i=L; i<=R; i++){ // 外层:遍历区间
int num = i;
while(num > 0){ // 内层:检查每一位
if(num % 10 == digit){
count++;
}
num = num / 10;
}
}
cout << "在" << L << "到" << R << "中,数字" << digit;
cout << "出现了" << count << "次" << endl;
return 0;
}
答案示例
- L=2, R=22时,数字2出现了6 次
(2,12,20,21,22中的2:2有1个,12有1个,20有1个,21有1个,22有2个)
三、循环嵌套记忆口诀
外层是"大哥",控制大事情
内层是"小弟",负责小细节
大哥走一步,小弟跑一圈
嵌套配合好,难题变简单
四、常见错误提醒
-
忘记初始化:内层循环的变量每次要重置
cpp// 错误:fact没有重置 // 正确:for(int i=1; i<=n; i++){ // long long fact = 1; // 每次重新开始 // for(int j=1; j<=i; j++)... -
循环条件写错 :注意是
<=还是<cpp// 计算阶乘时: for(int j=1; j<=i; j++) // 正确:要乘到i for(int j=1; j<i; j++) // 错误:少乘了一次 -
大数溢出 :阶乘增长很快,用
long longcpplong long fact = 1; // 能存更大的数 int fact = 1; // 容易溢出
五、练习题
- 先画流程图:用方框和箭头表示循环
- 手动模拟:选小数字(n=3)手动算一遍
- 分步调试:先写内层循环,测试通过再加外层
- 举生活例子:把问题变成"每天做几次练习"来理解