返回 课程

信奥AC之路-1级

0% 完成
0/0 步骤
  1. 第1课 开发环境与基础输出
    5 主题|小节
  2. 第2课 算术运算符
    7 主题|小节
  3. 第3课 printf与运算输出
    7 主题|小节
  4. 第4课 数的进制与拆位
    6 主题|小节
  5. 第5课 变量与基础运算
    17 主题|小节
  6. 第6课 常量与取整运算
    8 主题|小节
  7. 第7课 关系运算
    8 主题|小节
  8. 第8课 逻辑运算
    9 主题|小节
  9. 第9课 输入与计算进阶
    10 主题|小节
  10. 第10课 if语句及双分支语句
    8 主题|小节
  11. 第11课 if语句及双分支进阶
    11 主题|小节
  12. 第12课 三目运算
    9 主题|小节
  13. 第13课 多分支、多if和switch语句
    11 主题|小节
  14. 第14课 循环(基本输出)
    7 主题|小节
  15. 第15课 循环(While+If)
    8 主题|小节
  16. 第16课 循环(计数、求和、求乘积)
    10 主题|小节
  17. 第17课 循环进阶(While+)
    8 主题|小节
  18. 第18课 do-while及while其他用法
    8 主题|小节
  19. 第19课 For循环基础
    9 主题|小节
  20. 第20课 For循环进阶
    8 主题|小节
课 进展
0% 完成

16.2.1 求和的基本概念

“求和就是计算多个数的总和。比如,我们要计算1到100中所有偶数的和,就可以使用循环求和来解决。”

求和的基本思路:

  1. 定义一个求和变量(通常命名为sum),初始值设为0
  2. 使用循环遍历所有可能的数
  3. 在循环中判断每个数是否满足条件,如果满足,将该数加入到求和变量中
  4. 循环结束后,求和变量的值就是满足条件的数的总和

16.2.2 实验一:输出1~n中所有的偶数的和

题目描述: 输入一个正整数n,计算并输出1到n中所有偶数的和。

样例输入

10

样例输出

30

代码实现

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sum = 0;  // 总和变量初始化为0
    int i = 2;    // 从第一个偶数2开始
    
    while(i <= n) {  // 循环到n
        sum += i;  // 加到总和中
        i += 2;    // 增加2,保持i为偶数
    }
    
    cout << sum;  // 输出总和
    return 0;
}

优化版本

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    // 计算偶数和的公式:2+4+6+...+2k = 2(1+2+3+...+k) = 2*k*(k+1)/2,其中k=n/2
    int k = n / 2;  // 计算有多少个偶数
    int sum = k * (k + 1);  // 计算偶数和
    
    cout << sum;  // 输出总和
    return 0;
}

思考

  1. 为什么sum的初始值设为0?
  2. 对于样例输入10,偶数有哪些?它们的和是多少?

解释

  1. sum初始化为0是因为一开始我们还没有加入任何数,总和为0。
  2. 1到10中的偶数有:2, 4, 6, 8, 10,共5个,总和为2+4+6+8+10=30。

16.2.3 实验二:输出m~n中所有的奇数的和

题目描述: 输入两个正整数m和n(保证m <= n),计算并输出m到n之间(包括m和n)所有奇数的和。

样例输入

1 10

样例输出

25

代码实现

#include <iostream>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;
    
    int sum = 0;  // 总和变量初始化为0
    
    // 调整m为第一个奇数
    if(m % 2 == 0) {
        m++;  // 如果m是偶数,调整为下一个奇数
    }
    
    int i = m;  // 从第一个奇数开始
    
    while(i <= n) {  // 循环到n
        sum += i;  // 加到总和中
        i += 2;    // 增加2,保持i为奇数
    }
    
    cout << sum;  // 输出总和
    return 0;
}

思考

  1. 代码如何确保只计算奇数的和?
  2. 对于样例输入1 10,奇数有哪些?它们的和是多少?

解释

  1. 首先调整m为第一个奇数(如果m本身是偶数,则加1),然后每次递增2,确保i始终是奇数。
  2. 1到10中的奇数有:1, 3, 5, 7, 9,共5个,总和为1+3+5+7+9=25。

16.2.4 实验三:输出m~n中所有是7的倍数的数的和

题目描述: 输入两个正整数m和n(保证m <= n),计算并输出m到n之间(包括m和n)是7的倍数的数的和。

样例输入

1 50

样例输出

196

代码实现

#include <iostream>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;
    
    int sum = 0;  // 总和变量初始化为0
    
    // 找到第一个大于等于m的7的倍数
    int i = m;
    if(i % 7 != 0) {
        i = i + (7 - i % 7);  // 调整为下一个7的倍数
    }
    
    while(i <= n) {  // 循环到n
        sum += i;  // 加到总和中
        i += 7;    // 增加7,保持i为7的倍数
    }
    
    cout << sum;  // 输出总和
    return 0;
}

思考

  1. 代码如何找到第一个大于等于m的7的倍数?
  2. 对于样例输入1 50,7的倍数有哪些?它们的和是多少?

解释

  1. 如果m本身不是7的倍数,我们需要找到下一个7的倍数。通过计算m % 7得到余数,然后加上(7 – 余数)就能得到下一个7的倍数。
  2. 1到50中的7的倍数有:7, 14, 21, 28, 35, 42, 49,共7个,总和为7+14+21+28+35+42+49=196。

16.2.5 实验四:输出n的所有因数的和

题目描述: 输入一个正整数n,计算并输出n的所有因数的和。

样例输入

12

样例输出

28

代码实现

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sum = 0;  // 总和变量初始化为0
    int i = 1;    // 从1开始检查
    
    while(i <= n) {  // 检查1到n的所有数
        if(n % i == 0) {  // 判断i是否为n的因数
            sum += i;  // 加到总和中
        }
        i++;  // 循环变量加1
    }
    
    cout << sum;  // 输出总和
    return 0;
}

优化版本

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sum = 0;  // 总和变量初始化为0
    int i = 1;    // 从1开始检查
    int sqrtn = sqrt(n);  // n的平方根
    
    while(i <= sqrt(n)) {  // 只需要检查到sqrt(n)
        if(n % i == 0) {  // 判断i是否为n的因数
            sum += i;  // i是因数,加到总和中
            if(i != n / i) {  // 如果i不等于n/i
                sum += (n / i);  // n/i也是因数,也加到总和中
            }
        }
        i++;  // 循环变量加1
    }
    
    cout << sum;  // 输出总和
    return 0;
}

思考

  1. 12的所有因数有哪些?它们的和是多少?
  2. 优化版本如何减少循环次数?

解释

  1. 12的因数有:1, 2, 3, 4, 6, 12,共6个,总和为1+2+3+4+6+12=28。
  2. 如果i是n的因数,那么n/i也是n的因数。通过只检查到sqrt(n)并同时处理因数对(i, n/i),可以显著减少循环次数。

16.2.6 实验五:输出m~n中所有的闰年的和

题目描述: 输入两个正整数m和n(保证m <= n),计算并输出m到n之间(包括m和n)所有闰年的年份的和。

样例输入

2000 2020

样例输出

12060

代码实现

#include <iostream>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;
    
    int sum = 0;  // 总和变量初始化为0
    int i = m;    // 从m开始循环
    
    while(i <= n) {  // 循环到n
        // 判断是否为闰年
        if((i % 4 == 0 && i % 100 != 0) || i % 400 == 0) {
            sum += i;  // 加到总和中
        }
        i++;  // 循环变量加1
    }
    
    cout << sum;  // 输出总和
    return 0;
}

思考

  1. 对于样例输入2000 2020,闰年有哪些?它们的年份和是多少?
  2. 使用什么方法可以直接计算特定范围内的闰年和?

解释

  1. 2000(能被400整除)、2004、2008、2012、2016、2020(能被4整除但不能被100整除)均为闰年,年份和为2000+2004+2008+2012+2016+2020=12060。
  2. 目前没有简单的数学公式可以直接计算闰年和,因为闰年的判断条件较为复杂,需要逐一检查。

16.2.7 实验六:计算1~n中是2的倍数或者是3的倍数的数的总和

题目描述: 输入一个正整数n,计算并输出1到n中所有是2的倍数或者是3的倍数的数的总和。

样例输入

10

样例输出

42

代码实现(方法一)

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sum = 0;  // 总和变量初始化为0
    int i = 1;    // 从1开始循环
    
    while(i <= n) {  // 循环到n
        if(i % 2 == 0 || i % 3 == 0) {  // 判断是否为2的倍数或3的倍数
            sum += i;  // 加到总和中
        }
        i++;  // 循环变量加1
    }
    
    cout << sum;  // 输出总和
    return 0;
}

代码实现(方法二)

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sum = 0;  // 总和变量初始化为0
    int i = 1;    // 从1开始循环
    
    while(i <= n) {  // 循环到n
        if(i % 2 == 0) {  // 判断是否为2的倍数
            sum += i;     // 加到总和中
        } else if(i % 3 == 0) {  // 如果不是2的倍数但是3的倍数
            sum += i;            // 加到总和中
        }
        i++;  // 循环变量加1
    }
    
    cout << sum;  // 输出总和
    return 0;
}

思考

  1. 两种方法的区别和优缺点是什么?
  2. 对于样例输入10,哪些数是2的倍数或3的倍数?它们的和是多少?

解释

  1. 方法一使用逻辑或(||)操作直接判断是否满足条件,代码简洁明了。方法二使用if-else if结构,分别处理2的倍数和只是3的倍数的情况,逻辑更清晰但效率相同。
  2. 1到10中,2的倍数有:2, 4, 6, 8, 10;3的倍数有:3, 6, 9。去重后,符合条件的数有:2, 3, 4, 6, 8, 9, 10,总和为2+3+4+6+8+9+10=42。

16.2.8 实验七:计算1~n中所有是5的倍数并且包含数字5的数的总和

题目描述: 输入一个正整数n(n<1000),计算并输出1到n中所有既是5的倍数又包含数字5的数的总和。

样例输入

100

样例输出

50

代码实现:(方法一)

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int sum = 0;  // 总和变量初始化为0
    int i = 1;    // 从5开始循环(第一个5的倍数)
    while(i <= n) {  // 循环到n
        int g = i % 10;       // 个位
        int s = i / 10 % 10;  // 十位
        int b = i / 100 % 10; // 百位
        if(i % 5 == 0 && (g == 5 || s == 5 || b == 5)) {  // 判断是否为5的倍数并且包含5
                sum += i;  // 加到总和中
        }
        i++; 
    }
    
    cout << sum;  // 输出总和
    return 0;
}

代码实现(方法二)

#include <iostream>
using namespace std;

int main() {
    int i, n, sum = 0;    // 定义变量i、n和总和sum
    cin >> n;             // 输入整数n
    i = 1;                // 初始化i为1
    
    while(i <= n) {       // 循环遍历1到n
        int g = i % 10;           // 获取i的个位数字
        int s = i / 10 % 10;      // 获取i的十位数字
        int b = i / 100 % 10;     // 获取i的百位数字
        
        if(i % 5 == 0) {          // 判断i是否为5的倍数
            if(g == 5) {          // 判断个位是否为5
                sum += i;         // 将i加到总和中
            }else if( s== 5){     // 判断十位是否为5
                sum += i;         // 将i加到总和中
            }else if(b == 5){     // 判断百位是否为5
                sum += i;         // 将i加到总和中
            }
        }
        i++;              // i自增1
    }
    
    cout << sum;          // 输出总和
    return 0;
}

代码实现(方法三)

#include <iostream>
using namespace std;

int main() {
    int i, n, sum = 0;    // 定义变量i、n和总和sum
    cin >> n;             // 输入整数n
    i = 1;                // 初始化i为1
    while(i <= n) {       // 循环遍历1到n
        // 判断i是否为5的倍数且包含数字5
        if(i % 5 == 0) {          // 判断i是否为5的倍数
            int g = i % 10;           // 获取i的个位数字
        	int s = i / 10 % 10;      // 获取i的十位数字
        	int b = i / 100 % 10;     // 获取i的百位数字
            if(g == 5 || s == 5 || b == 5) {  // 判断是否包含数字5
                sum += i;         // 将i加到总和中
            }
        }
        i++;              // i自增1
    }
    
    cout << sum;          // 输出总和
    return 0;
}

代码实现(方法四)

#include <iostream>
using namespace std;

int main() {
    int i, n, sum = 0;    // 定义变量i、n和总和sum
    cin >> n;             // 输入整数n
    i = 5;                // 初始化i为5,第一个满足条件的数
    while(i <= n) {       // 循环遍历符合条件的数
        int g = i % 10;           // 获取i的个位数字
        int s = i / 10 % 10;      // 获取i的十位数字
        int b = i / 100 % 10;     // 获取i的百位数字
        
        // 判断是否包含数字5
        if(g == 5 || s == 5 || b == 5) {
            sum += i;     // 将i加到总和中
        }
        
        i += 5;           // i增加5,保持是5的倍数
    }
    cout << sum;          // 输出总和
    return 0;
}

思考

每种写法循环的次数和判断是如何执行的

16.2.9 实验八:计算1~n中是3的倍数的奇数的总和

题目描述: 输入一个正整数n,计算并输出1到n中所有是3的倍数且为奇数的数的总和。

样例输入

20

样例输出

30

代码实现(方法一)

#include <iostream>
using namespace std;

int main() {
    int i, n, sum = 0;   // 定义变量i、n和总和sum
    cin >> n;            // 输入整数n
    i = 1;               // 初始化i为1
    
    while(i <= n) {      // 循环遍历1到n
        if(i % 2 != 0 && i % 3 == 0) {  // 判断i是否为奇数且是3的倍数
            sum += i;    // 将符合条件的数加到总和中
        }
        i++;             // i自增1
    }
    
    cout << sum;         // 输出总和
    return 0;
}

代码实现(方法二)

#include <iostream>
using namespace std;

int main() {
    int i, n, sum = 0;   // 定义变量i、n和总和sum
    cin >> n;            // 输入整数n
    i = 1;               // 初始化i为1
    
    while(i <= n) {      // 循环遍历1到n
        if(i % 2 != 0) {  // 判断i是否为奇数
            if(i % 3 == 0) {  // 判断i是否为3的倍数
                sum += i;    // 将符合条件的数加到总和中
            }
        }
        i++;             // i自增1
    }
    
    cout << sum;         // 输出总和
    return 0;
}

代码实现(方法三)

#include <iostream>
using namespace std;

int main() {
    int i, n, sum = 0;   // 定义变量i、n和总和sum
    cin >> n;            // 输入整数n
    i = 3;               // 初始化i为3,第一个奇数且是3的倍数的数
    
    while(i <= n) {      // 循环遍历符合条件的数
        sum += i;        // 将i加到总和中
        i += 6;          // i增加6,跳到下一个奇数且是3的倍数的数
    }
    
    cout << sum;         // 输出总和
    return 0;
}

思考

  1. 三种方法的运行过程及优点是什么?
  2. 为什么方法三从3开始,每次增加6?

解释

  1. 方法一使用两个条件判断,直接判断是否为奇数且是3的倍数;方法二使用嵌套判断,先判断奇数再判断是否为3的倍数;方法三直接从第一个符合条件的数(3)开始,每次增加6,不需要额外判断条件。
  2. 方法三从3开始是因为3是第一个既是奇数又是3的倍数的数。每次增加6是因为3的倍数中,相邻的奇数之间的间隔是6(如3, 9, 15…)。因为偶数个3的倍数是偶数,奇数个3的倍数是奇数,所以奇数的3倍数需要间隔6。