返回 课程

信奥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 主题|小节
课 16, 主题|小节 7
进行中

16.6 循环练习题

2025年9月22日
课 进展
0% 完成

练习题1:计数问题

题目描述: 输入两个正整数m和n,计算并输出m到n之间(包括m和n)中既是3的倍数又是5的倍数的数的个数。

样例输入

1 100

样例输出

6

代码框架

#include <iostream>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;
    
    // 请补充代码,计算并输出满足条件的数的个数
    
    return 0;
}

答案

#include <iostream>
using namespace std;

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

解析: 既是3的倍数又是5的倍数,就是15的倍数。我们可以直接找到第一个大于等于m的15的倍数,然后每次增加15,这样就能只遍历15的倍数。对于样例1 100,满足条件的数有:15, 30, 45, 60, 75, 90,共6个数。

练习题2:求和问题

题目描述: 输入一个正整数n,计算并输出1到n之间所有能被3整除的数的平方和。

样例输入

10

样例输出

126

代码框架

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    // 请补充代码,计算并输出满足条件的数的平方和
    
    return 0;
}

答案

#include <iostream>
using namespace std;

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

解析: 我们需要计算1到n之间所有3的倍数的平方和。对于n=10,3的倍数有:3, 6, 9,它们的平方和为3²+6²+9²=9+36+81=126。

练习题3:求乘积问题

题目描述: 输入一个正整数n,计算并输出 n!/(1×3×5×…×(2n-1)) 的值(保留两位小数)。

样例输入

5

样例输出

0.13

代码框架

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    // 请补充代码,计算并输出满足条件的值
    
    return 0;
}

答案

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

int main() {
    int n;
    cin >> n;
    
    double fact = 1.0;  // 计算n!
    double prod = 1.0;  // 计算1×3×5×...×(2n-1)
    int i = 1;
    
    // 计算n!
    while(i <= n) {
        fact *= i;
        i++;
    }
    
    // 计算1×3×5×...×(2n-1)
    i = 1;
    while(i <= n) {
        prod *= (2 * i - 1);
        i++;
    }
    
    // 计算结果
    double result = fact / prod;
    
    cout << fixed << setprecision(2) << result;  // 输出结果,保留两位小数
    return 0;
}

解析: 这个问题需要计算n!除以所有小于等于2n-1的奇数的乘积。对于n=5,计算5!/(1×3×5×7×9)=120/945≈0.127。四舍五入保留两位小数得到0.13。

练习题4:综合应用题

题目描述: 输入两个正整数m和n,计算并输出m到n之间(包括m和n)中同时满足以下条件的数的个数和总和:

  1. 是偶数
  2. 能被3整除

样例输入

1 20

样例输出

3
36

代码框架

#include <iostream>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;
    
    // 请补充代码,计算并输出满足条件的数的个数和总和
    
    return 0;
}

答案

#include <iostream>
using namespace std;

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

解析: 同时是偶数和3的倍数的数,就是6的倍数。我们可以直接找到第一个大于等于m的6的倍数,然后每次增加6,这样就能只遍历6的倍数。对于样例1 20,满足条件的数有:6, 12, 18,共3个数,总和为6+12+18=36。

练习题5:计数和总和

题目描述: 输入一个正整数n,计算并输出1到n中所有能被4整除但不能被6整除的数的个数和总和。

样例输入

20

样例输出

3
28

代码框架

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    // 请补充代码,计算并输出满足条件的数的个数和总和
    
    return 0;
}

答案

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int cnt = 0;  // 计数变量初始化为0
    int sum = 0;  // 总和变量初始化为0
    int i = 4;    // 从第一个4的倍数开始
    
    while(i <= n) {  // 循环到n
        if(i % 6 != 0) {  // 如果不是6的倍数
            cnt++;        // 计数加1
            sum += i;     // 加到总和中
        }
        i += 4;  // 增加4,保持i为4的倍数
    }
    
    cout << cnt << endl;  // 输出个数
    cout << sum;          // 输出总和
    return 0;
}

解析: 能被4整除但不能被6整除的数是指那些是4的倍数但不是12的倍数的数。我们可以从4开始,每次增加4,判断当前数是否为6的倍数。对于样例20,满足条件的数有:4, 8, 16,共3个,总和为4+8+16=28。

选择题

选择题1:以下代码计算的是什么?

int sum = 0, i = 1;
while(i <= n) {
    if(i % 2 == 0) {
        sum += i;
    }
    i++;
}

A. 1到n的所有数的和 B. 1到n的所有偶数的和 C. 1到n的所有奇数的和 D. 1到n的所有能被2整除的数的和

答案:B. 1到n的所有偶数的和

解析: 代码中条件i % 2 == 0检查i是否为偶数,如果是,则将i加入sum中。因此,这段代码计算的是1到n中所有偶数的和。

选择题2:以下代码的输出是什么?(假设n=10)

int count = 0, i = 1;
while(i <= n) {
    if(i % 3 == 0) {
        count++;
    }
    i++;
}
cout << count;

A. 3 B. 4 C. 10 D. 0

答案:A. 3

解析: 代码计算1到n之间能被3整除的数的个数。当n=10时,这些数是3, 6, 9,共3个,所以输出为3。

选择题3:以下代码计算的是什么?

int product = 1, i = 1;
while(i <= n) {
    product *= i;
    i++;
}

A. n的阶乘 B. 1到n的所有数的和 C. 1到n的所有偶数的乘积 D. n的平方

答案:A. n的阶乘

解析: 代码从1开始,将每个数乘入product中,直到n。这正是计算n的阶乘(n!)的过程:n! = 1×2×3×…×n。

选择题4:在计算m到n之间所有偶数的和时,下面哪个初始值设置是正确的?

int sum = ?, i = ?;

A. sum = 0, i = m B. sum = 1, i = m C. sum = 0, i = m+1 D. sum = m, i = m

答案:A. sum = 0, i = m

解析: 求和变量sum应该初始化为0,因为一开始还没有加入任何数。循环变量i应该从m开始,然后在循环内部判断i是否为偶数。

选择题5:计算1到n中所有3的倍数的个数时,以下哪个代码片段是不正确的?

A.

int cnt = 0;
for(int i = 1; i <= n; i++) {
    if(i % 3 == 0) cnt++;
}

B.

int cnt = 0;
for(int i = 3; i <= n; i += 3) {
    cnt++;
}

C.

int cnt = n / 3;

D.

int cnt = (n + 2) / 3;

答案:C.

解析: 方法C int cnt = n / 3; 对于某些特定情况是正确的,但它忽略了n可能不是3的倍数的情况。例如,对于n=10,3的倍数有3,6,9,共3个,等于10/3=3(整数除法)。而n=11时,3的倍数仍然是3个,但11/3=3(整数除法),所以偶然是对的。但对于n=8,3的倍数有3,6,共2个,而8/3=2(整数除法)。因此C不是普遍正确的方法,而正确答案应该是使用循环计数或者使用公式 (n + 2) / 3

选择题6:对于计算n的所有因数的和,以下哪种方法最高效?

A.

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

B.

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

C.

int sum = 0;
for(int i = 1; i*i <= n; i++) {
    if(n % i == 0) {
        sum += i;
        if(i != n/i) sum += n/i;
    }
}

D.

int sum = 1 + n;

答案:C.

int sum = 0;
for(int i = 1; i*i <= n; i++) {
    if(n % i == 0) {
        sum += i;
        if(i != n/i) sum += n/i;
    }
}

解析: 方法C只需要检查到sqrt(n)(n的平方根),,然后对每个因数i,同时处理另一个因数n/i,大幅减少了循环次数,是最高效的方法。

选择题7:计算m到n之间所有奇数的和,如果m是偶数,下面哪个代码片段是不正确的?

A.

int sum = 0;
for(int i = m; i <= n; i++) {
    if(i % 2 != 0) sum += i;
}

B.

int sum = 0;
for(int i = m+1; i <= n; i += 2) {
    sum += i;
}

C.

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

D.

int sum = (m + n) * ((n - m + 1) / 2);

答案:D.

解析: 方法D int sum = (m + n) * ((n - m + 1) / 2); 尝试使用等差数列求和公式,但错在没有考虑奇数的特性。如果m是偶数,则第一个奇数是m+1;该公式计算的是所有数的和,而不仅仅是奇数的和。正确的公式应该基于奇数序列的特点。

选择题8:计算n的阶乘时,以下哪个循环是最高效的?

A.

int fact = 1;
for(int i = 1; i <= n; i++) {
    fact *= i;
}

B.

int fact = n;
for(int i = n-1; i >= 1; i--) {
    fact *= i;
}

C.

int fact = 1;
int i = 1;
while(i <= n) {
    fact *= i++;
}

D. 它们的效率相同

答案:D. 它们的效率相同

解析: 这三种方法在计算阶乘时的时间复杂度都是O(n),因此效率相同。实际执行时,可能由于编译器优化和硬件特性会有微小差异。

选择题9:下面哪个代码片段能正确计算1到n中所有数的平方和?

A.

int sum = 0;
for(int i = 1; i <= n; i++) {
    sum += i * i;
}

B.

int sum = n * (n + 1) / 2;

C.

int sum = n * (n + 1) * (2 * n + 1) / 6;

D.

int sum = 0;
for(int i = 1; i <= n; i++) {
    sum += i;
}
sum *= sum;

答案:A和C

解析: 1到n的平方和可以用公式n(n+1)(2n+1)/6计算(选项C),也可以通过循环直接计算(选项A)。选项B计算的是1到n的和,选项D计算的是(1+2+…+n)²,都不是平方和。

选择题10:计算1到n之间所有能被3整除或能被5整除的数的和,以下哪种方法是正确的?

A.

int sum = 0;
for(int i = 1; i <= n; i++) {
    if(i % 3 == 0 || i % 5 == 0) {
        sum += i;
    }
}

B.

int sum = 0;
for(int i = 3; i <= n; i += 3) {
    sum += i;
}
for(int i = 5; i <= n; i += 5) {
    sum += i;
}

C.

int sum = 0;
for(int i = 3; i <= n; i += 3) {
    sum += i;
}
for(int i = 5; i <= n; i += 5) {
    if(i % 3 != 0) {
        sum += i;
    }
}

D.

int sum3 = 3 * (n / 3) * (n / 3 + 1) / 2;
int sum5 = 5 * (n / 5) * (n / 5 + 1) / 2;
int sum15 = 15 * (n / 15) * (n / 15 + 1) / 2;
int sum = sum3 + sum5 - sum15;

答案:AC.

int sum = 0;
for(int i = 3; i <= n; i += 3) {
    sum += i;
}
for(int i = 5; i <= n; i += 5) {
    if(i % 3 != 0) {
        sum += i;
    }
}

解析: 方法B会导致15的倍数被重复计算两次。方法C先计算所有3的倍数的和,然后加上那些是5的倍数但不是3的倍数的数,避免了重复计算,是正确且高效的方法。方法D的公式有误。

判断题

判断题1:在进行连续乘积计算时,乘积变量的初始值应该设为0。

答案:错误

解析: 在进行连续乘积计算时,乘积变量的初始值应该设为1,而不是0。因为任何数乘以0都等于0,如果初始化为0,结果将永远是0。

判断题2:计算1到n中所有奇数的和时,可以直接从1开始,每次增加2。

答案:正确

解析: 所有奇数可以表示为2k+1的形式,因此从1开始,每次增加2(步长为2),可以遍历所有的奇数。这比遍历所有数再判断是否为奇数更高效。

判断题3:在计算n的所有因数的和时,必须遍历从1到n的所有数。

答案:错误

解析: 不需要遍历所有1到n的数。我们只需要遍历到sqrt(n),因为如果i是n的因数,那么n/i也是n的因数。这样可以显著减少循环次数。

判断题4:对于任意正整数n,从1到n的所有数的和等于n*(n+1)/2。

答案:正确

解析: 1到n的所有数的和可以用等差数列求和公式计算:Sn = n*(a1+an)/2 = n*(1+n)/2 = n*(n+1)/2。

判断题5:从1到n的所有偶数的个数等于n/2。

答案:正确

解析: 从1到n中,偶数的个数是[n/2](向下取整)。例如,对于n=10,偶数有:2, 4, 6, 8, 10,共5个,等于10/2=5。

判断题6:计算m到n中所有数的乘积时,如果m大于n,结果应该是0。

答案:错误

解析: 如果m大于n,表示范围内没有数,乘积应该是1(乘法单位元),而不是0。这是因为任何数乘以1等于其本身,1是乘法的基础。

判断题7:计算等差数列1, 3, 5, …, (2n-1)的和,结果等于n²。

答案:正确

解析: 这是一个首项为1,公差为2,有n项的等差数列。使用等差数列求和公式:Sn = n*(a1+an)/2 = n*(1+(2n-1))/2 = n*2n/2 = n²。

判断题8:计算1到n中能被3整除的数的个数,结果等于[n/3](向下取整)。

答案:正确

解析: 从1到n中,3的倍数有:3, 6, 9, …, 3*[n/3],共[n/3]个。例如,对于n=10,3的倍数有:3, 6, 9,共3个,等于10/3=3(向下取整)。

判断题9:计算n的所有因数的个数时,如果n是质数,结果应该是2。

答案:正确

解析: 质数的定义是只有1和它本身两个因数的数。因此,如果n是质数,它的因数个数必定是2。

判断题10:关于循环求和,sum += i 和 sum = sum + i 的效果是完全相同的。

答案:正确

解析: 这两种写法在功能上是等价的,都是将i的值加到sum上。sum += i 是一种简写形式,通常更为简洁,但实际效果与 sum = sum + i 相同。