第四章 循环结构的程序设计
第一节 for语句
2016:【例4.1】for循环求和
提示
循环累加
代码
#include <bits/stdc++.h>
using namespace std;
int sum, n;
int main(){
cin >> n;
for (int i = 1; i <= n; i++) sum += i;
cout << sum << '\n';
return 0;
}
2017:【例4.2】输出偶数
提示
for 循环,结合 if 语句判断 i 是不是偶数
代码
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
if (i % 2 == 0) cout << i << ' ';
return 0;
}
2018:【例4.3】输出奇偶数之和
2019:【例4.4】求阶乘
1059:求平均年龄
累加求和,求平均数
求平均数的时候,需要注意,强制转换,还有保留小数
printf("%.2lf", ...);
1060:均值
1061:求整数的和与均值
1062:最高的分数
1063:最大跨度值
提示
这也是打擂台
但这次,我们要求出最大值,还有最小值
代码
#include <bits/stdc++.h>
using namespace std;
int maxn = -1;
int minn = 1001;
int main() {
int n;
cin >> n;
while (n--) {
int x;
cin >> x;
maxn = max(maxn, x);
minn = min(minn, x);
}
cout << maxn - minn << endl;
return 0;
}
1064:奥运奖牌计数
提示
这是满足条件的,累加求和
循环读入,刚开始可能不会操作
提示2
while (n--) {
cin >> a >> b >> c;
suma += a, sumb += b, sumc += c;
}
1065:奇数求和
提示
for 循环,从 l 枚举到 r,[l, r]
判断 i 是不是 奇数
累加求和
if (i % 2 == 1) ...
if (i % 2) ... // 这样写,也是 ok 的
if (i & 2) ... // 这样写,更是 ok 的
1066:满足条件的数累加
1067:整数的个数
1068:与指定数字相同的数的个数
1069:乘方计算
提示
我们先理解一下,指数
\(a^b\),表示 b 个 a 相乘
提示2
注意开long long
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, n;
cin >> a >> n;
long long res = 1ll;
while (n--) {
res *= a;
}
printf("%lld\n", res);
return 0;
}
1070:人口增长
提示
这是一个数学课本里一个统计的应用题
我们要先理解一下,百分数
\(1 \%\),表示 \(1 * 0.01\),即 \(0.01\)
\(0.1 \%\),表示 \(0.1 * 0.01\),即 \(0.001\)
每年0.1%的增长,那就是 1 * 1.001
1071:菲波那契数
提示
循环迭代
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int a = 1, b = 1, c;
if (n <= 2) {
cout << 1 << endl;
return 0;
}
for (int i = 3; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
cout << c << endl;
return 0;
}
代码2
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int a = 1, b = 1, c = 1; // 在这里,对c进行初始化,就可以解决n<=2的情况
for (int i = 3; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
cout << c << endl;
return 0;
}
1072:鸡尾酒疗法
提示
首先,读题要多读几遍。这个题面,相对比较长,有点饶
重点看,输入数据的描述:第一行为鸡尾酒疗法的数据,其余各行为各种改进疗法的数据。
所以,对应的样例1,输入是5,第1行是原数据,剩余的4行为改进数据。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
int n, m;
cin >> n >> m;
double jiwei = m * 1.0 / n;
for (int i = 1; i < T; i++) {
cin >> n >> m;
double newjiwei = m * 1.0 / n;
if (newjiwei - jiwei > 0.05) cout << "better" << endl;
else if (jiwei - newjiwei > 0.05) cout << "worse" << endl;
else cout << "same" << endl;
}
return 0;
}
1073:救援
提示
这个题目,稍有难度,难度在读题上,这是一个应用题的题面
还有对直角坐标系的认识
已知点的坐标,求距离原点的距离,就是求线段的长度,用到了勾股定理
给你一个点,路程,使用勾股定理求解(勾股定理,知道吗?不知道,百度一下)
求出斜边,就是路程,sqrt(a * a + b * b)
模拟,去+上人+回+下人
有几个点,就循环几次,每次输入屋顶的坐标

提示2
注意阅读输入描述:
每一行上包含两个表示屋顶相对于大本营的平面坐标位置的实数
代码
#include <iostream>
#include <cmath>
using namespace std;
double ret;
int main(){
int n;
cin >> n;
while (n--){
double x, y;
int z;
cin >> x >> y >> z;
ret += sqrt(x * x + y * y) * 2 / 50 + 1.5 * z;
}
cout << (int)ceil(ret) << '\n';
return 0;
}
1074:津津的储蓄计划
提示
这题,也是应用题的题面
要先对两个样例,进行手动模拟
列这样的表格,我写一下表头,
月份,月初津津有多少钱,预算花多少,花完剩余多少,妈妈的钱数,月底津津有多少
1 300 290 10 0 10
2 310 230 80 0 80
把样例1,和样例2,都这样模拟一遍,在纸质草稿纸上,进行
然后再说写代码的事情
写代码就是for 循环,从1到12,表示月份。模拟每个月的执行过程
代码
#include <bits/stdc++.h>
using namespace std;
int jinjin, mama;
bool flag;
int main(){
for (int i = 1; i <= 12; i++){
int x;
cin >> x;
jinjin += 300;
if (jinjin < x){
cout << '-' << i << '\n';
flag = true;
break;
}
jinjin -= x;
mama += jinjin / 100 * 100;
jinjin %= 100;
}
if (!flag){
cout << jinjin + mama * 1.2 << '\n';
}
return 0;
}
1075:药房管理
提示
应用题的题面
药品总量是m,有n个人
循环,判断当前这个人要拿的要是否够
如果不够,计数器++
如果够,更新m的数值(减去当前这个人拿的药)
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int m, n;
cin >> m >> n;
int cnt = 0;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
if (x > m) cnt++;
else m -= x;
}
cout << cnt << endl;
return 0;
}
1076:正常血压
提示
循环输入,每次输入两个数
判断是否满足正常血压的条件
如果满足,计数器++,打擂台
如果不满足,计数器清零
这题较难,放在最后做
代码
#include <iostream>
using namespace std;
int ret, cnt;
int main(){
int n;
cin >> n;
while (n--){
int a, b;
cin >> a >> b;
if (a >= 90 && a <= 140 && b >= 60 && b <= 90){
cnt++;
ret = max(ret, cnt);
}
else{
cnt = 0;
}
}
cout << ret;
return 0;
}
1077:统计满足条件的4位数
提示
这是数位拆分
因为已经给定了是四位数
循环n次,每次输入一个数x
个位是 i % 10
十位是 i / 10 % 10
百位是 i / 100 % 10
千位是 i / 1000
判断满足条件,cnt++
1078:求分数序列和
提示
这题,有一定难度
难度在于,看不懂那个数列
怎么才能让自己看懂呢? 在笔记本上,抄写一遍,就能看懂了
然后我们要尝试发现规律,是有规律的
计算每一项求和的时候
每一次
sum += 1.0 * q / p;
并注意 q 和 p,要进行迭代变化
代码
#include <iostream>
using namespace std;
int n;
double sum;
int main(){
cin >> n;
int q = 2, p = 1;
for (int i = 1; i <= n; i++){
sum += 1.0 * q / p;
int t = p;
p = q;
q = q + t;
}
printf("%.4lf\n", sum);
return 0;
}
1079:计算分数加减表达式的值
提示
首先是一个多项式,每一项都是一个分数
要注意 1/i
强制转换的问题(1.0 / i
)
通过观察还发现,每一项正负交替
我们可以通过判断i的奇偶性(i % 2
),控制是 +=
, 还是 -=
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
double sum = 0.0;
for (int i = 1; i <= n; i++){
if (i % 2 == 1) sum += 1.0 / i;
else sum -= 1.0 / i;
}
printf("%.4lf\n", sum);
return 0;
}
1080:余数相同问题
提示
这个题目,就是一个枚举,从小到大枚举
从多小?2
到多大?无限
for (int x = 2; ; x++) ...
这样就可以实现,无限循环
当满足条件,写一个if语句
找到答案,输出
break 跳出循环
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b, c;
cin >> a >> b >> c;
for (int x = 2; ; x++) {
if (a % x == b % x && b % x == c % x) {
cout << x;
break;
}
}
return 0;
}
1081:分苹果
提示
要认真读题
思考怎么分,才是总数最少
在看样例,输入是 8,怎么得到的 36(一定要用草稿纸)
然后你就知道是什么了
代码
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int sum = 0;
for (int i = 1; i <= n; i++)
sum += i;
cout << sum;
return 0;
}
代码2
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
cout << (1 + n) * n / 2 << '\n';
return 0;
}
1082:求小数的某一位
提示
n 是 10000, 不能通过 printf("%.nlf", ...)
语句进行输出
本质上,要进行类似竖式除法的模拟
一位小数的一位小数的算
提示2
a * 10 / b
用 a 每次乘上 10,表示向右移动一位小数
a = a * 10 % b
这个是用来表示每次除完之后的余数
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b, n;
cin >> a >> b >> n;
int ret;
while (n--) {
ret = a * 10 / b;
a = a * 10 % b;
}
cout << ret << '\n';
return 0;
}
1083:计算星期几
提示
我们要理解,指数
然后要理解,星期几是7天一循环的
所以,和 \(a^b\) 具体是几,没有关系
和 \(%7\) 的结果有没有关系
提示2
随时取模
周几的计算结果,之和 \(%7\) 有关,那么,我们只需要保留余数就可以了
幂次运算,很容易爆炸,开longlong也没用。
所以,一定要,随时取模
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
int t = 1;
for (int i = 0; i < b; i++) {
t *= a;
t %= 7;
}
if (t == 0) cout << "Sunday" << '\n';
if (t == 1) cout << "Monday" << '\n';
if (t == 2) cout << "Tuesday" << '\n';
if (t == 3) cout << "Wednesday" << '\n';
if (t == 4) cout << "Thursday" << '\n';
if (t == 5) cout << "Friday" << '\n';
if (t == 6) cout << "Saturday" << '\n';
return 0;
}
代码2
#include <bits/stdc++.h>
using namespace std;
string ans[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int main() {
int a, b;
cin >> a >> b;
int t = 1;
for (int i = 0; i < b; i++) {
t *= a;
t %= 7;
}
cout << ans[t] << endl;
return 0;
}
1084:幂的末尾
提示
我们只关心末3位,即只需要 % 1000
每一次循环累乘的时候,取模
随时取模
提示2
若幂本身不足三位,在前面补零
这种情况,我们使用 if 进行判断,分情况输出
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
int res = 1;
for (int i = 1; i <= b; i++) {
res *= a;
res %= 1000;
}
if (res < 10) cout << "00" << res << endl;
else if (res < 100) cout << "0" << res << endl;
else cout << res << endl;
return 0;
}
第二节 while语句
2020:【例4.5】第几项
提示
累加求和,当超过 m 的时候,break
使用while
while (true){
i++;
s += i;
if (s > m) break;
}
使用for
for (i = 1; ; i++){
s += i;
if (s > m) break;
}
for (i = 1; s <= m; i++){
s += i;
}
2021:【例4.6】最大公约数
提示
使用 for 从大到小,枚举一遍,哪个数同时是 m 和 n 的公约数
这里面要从大到小枚举
大是多大?min(m, n)
小是多小?1
代码
#include <iostream>
using namespace std;
int n, m;
int ret;
int main() {
cin >> n >> m;
for (int i = max(n, m); i >= 1; i--){
if (n % i == 0 && m % i == 0){
ret = i;
break;
}
}
cout << ret << '\n';
return 0;
}
2022:【例4.7】最小n值
提示
都是累加求和,满足一定条件的情况下,break
特殊一点是的,这里面是很多个分式累加
1 / i
会自动向下取整,不能得到我们想要的小数结果
这里要注意强制转换
代码
#include <bits/stdc++.h>
using namespace std;
double sum;
int main() {
int m;
cin >> m;
int n = 0;
while (sum < m) {
n++;
sum += 1.0 / n;
}
cout << n << '\n';
return 0;
}
2023:【例4.8】数据统计
提示
没有告诉有几个数,属于不定次输入(在教程中搜索“不定次输入”复习一下)
打擂台,求最值。这是常规操作
求平均数,也需要注意强制转换
输出的时候,控制保留3位小数 printf("%.3lf", ...)
代码
#include <bits/stdc++.h>
using namespace std;
int x;
int maxn = -2e9, minn = 2e9;
int sum, n;
int main() {
while (cin >> x){
maxn = max(maxn, x);
minn = min(minn, x);
sum += x;
n++;
}
printf("%d %d %.3lf\n", minn, maxn, 1.0 * sum / n);
return 0;
}
1085:球弹跳高度的计算
提示
难度在哪呢?在理解题面上
如何才能看得懂呢?画图,标画上10次落地的过程
在每个弹起的顶点,直接标上 几分之几 h
最后,你会发现,这直接是一个很多个分式求和
提示2
也可以写循环,模拟10次落地的过程
难点在于,总是多算一点,少算一点
试一试
代码
#include<bits/stdc++.h>
using namespace std;
int main() {
double h, sum=0, last;
cin >> h;
sum = h + h + h/2 + h/4 + h/8 + h/16
+ h/32 + h/64 + h/128 + h/256;
last = h/1024;
cout << sum << endl << last;
return 0;
}
代码2
#include<iostream>
using namespace std;
double ans;
int main() {
cin>> ans;
double sum = ans;
for(int i = 1; i<10; i++) {
sum += ans;
ans /= 2;
}
cout<< sum <<'\n' << ans / 2 << '\n';
return 0;
}
1086:角谷猜想
提示
告诉我们规则,我们去执行
难点在于,怎么控制这个输出
// 使用printf, 格式化输出语句,就方便很多
printf("%d*3+1=%d\n", n, n * 3 + 1);
printf("%d/2=%d\n", n, n / 2);
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
while (n != 1) {
if (n % 2 == 1) {
printf("%d*3+1=%d\n", n, n * 3 + 1);
n = n * 3 + 1;
} else {
printf("%d/2=%d\n", n, n / 2);
n = n / 2;
}
}
printf("End\n");
return 0;
}
代码2
#include<iostream>
using namespace std;
int main() {
int n;
cin>>n;
while(true) {
if(n==1) {
cout<<"End";
break;
}
if(n%2==0) {
cout<<n<<"/2="<<n/2<<endl;
n/=2;
} else {
cout<<n<<"*3+1="<<n*3+1<<endl;
n=n*3+1;
}
}
return 0;
}
1087:级数求和
提示
需要注意,每一项的分式,要强制转换
1.0 / i
代码
#include<bits/stdc++.h>
using namespace std;
double s = 0;
int k;
int n = 1;
int main() {
cin >> k;
for(int i = 1; s <= k; i++) {
s += 1.0 / i;
n = i;
}
cout << n;
return 0;
}
1088:分离整数的各个数
提示
这是典型的数位拆分
while (n) {
cout << n % 10;
n /= 10;
}
在教程上,搜索“数位拆分”,进行复习
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
while (n) {
cout << n % 10 << ' ';
n /= 10;
}
return 0;
}
1089:数字反转
提示
这道题目,特殊的地方是,负数怎么处理
我们首先要回顾,整数带余除法的公式
理解一下,负数的余数问题(a = k * b + r,对于负数,也适用这个式子)
回忆结论:余数的正负号,和被除数有关
其他的,就是常规操作了
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int t = 0;
while (n) {
t = t * 10 + n % 10;
n /= 10;
}
cout << t;
return 0;
}
1090:含k个3的数
提示
能够被19整除,同时恰好有k个3
这是一个逻辑与的关系
有k个3的判断,依然是数位拆分操作
代码
#include <iostream>
using namespace std;
int main() {
int m, k;
cin >> m >> k;
bool flag = false;
if (m % 19 != 0) flag = true;
int cnt = 0;
while (m) {
if (m % 10 == 3) cnt++;
m /= 10;
}
if (cnt != k) flag = true;
if (flag) cout << "NO";
else cout << "YES";
return 0;
}
代码2
#include <bits/stdc++.h>
using namespace std;
int m, k;
int check(int x){
int sum = 0;
while (x){
if (x % 10 == 3) sum++;
x /= 10;
}
return sum;
}
int main(){
cin >> m >> k;
if (m % 19 == 0 && check(m) == k) cout << "YES" << '\n';
else cout << "NO" << '\n';
return 0;
}
第三节 do-while语句
第四节 循环嵌套
2026:【例4.12】阶乘和
2027:【例4.13】三角形
2028:【例4.14】百钱买百鸡
2029:【例4.15】水仙花数
2030:【例4.16】找素数
2031:【例4.17】四位完全平方数
2032:【例4.18】分解质因数
2033:【例4.19】阶乘之和
1091:求阶乘的和
1092:求出e的值
1093:计算多项式的值
1094:与7无关的数
1095:数1的个数
1096:数字统计
1097:画矩形
1098:质因数分解
1099:第n小的质数
1100:金币
1101:不定方程求解