跳转至

第四章 循环结构的程序设计

第一节 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】输出奇偶数之和

 2017:【例4.2输出偶数 类似

2019:【例4.4】求阶乘

累加求和变成了累乘求积
道理一样

1059:求平均年龄

累加求和求平均数
求平均数的时候需要注意强制转换还有保留小数
printf("%.2lf", ...);

1060:均值

 1059求平均年龄 类似

1061:求整数的和与均值

 1060均值 类似

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:满足条件的数累加

 1065奇数求和 类似

1067:整数的个数

 1065奇数求和 类似
这回是统计计数

1068:与指定数字相同的数的个数

 1067整数的个数 类似
统计计数

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:菲波那契数

提示

循环迭代

c = a + b;
a = b;
b = c;
代码
#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)

模拟,去+上人+回+下人

有几个点,就循环几次,每次输入屋顶的坐标

image-20251009204035427

提示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:幂的末尾

 1083计算星期几 类似
提示

我们只关心末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值

这个和 2020:【例4.5第几项是雷同的
提示

都是累加求和,满足一定条件的情况下,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:级数求和

这个和 2022:【例4.7最小n值 是雷同的
提示

需要注意,每一项的分式,要强制转换

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:不定方程求解