练习题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)中同时满足以下条件的数的个数和总和:
- 是偶数
- 能被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 相同。