周期规律取模运算分支结构
求三色彩球的颜色。有数量无限的红(Red)绿(Green)蓝(Blue)三种彩球排成一行,每组先为5个红色球,随后3个绿色,最后为2个蓝色。每个球都有编号,从左到右依次为1,2,3……。输入整数代表编号,求该编号球的颜色。下面是C++代码是实现,正确说法是()。
int N, remainder;
cin >> N;
remainder = N % 10; // remainder变量保存余数
if((1 <= remainder) && (remainder <= 5))
cout << "Red";
else if ((6 <= remainder) && (remainder <= 8))
cout << "Green";
else if ((remainder == 9) || (remainder == 0))
cout << "Blue";
A.将 else if ((remainder == 9) || (remainder == 0)) 修改为 else 效果相同
B.将 ((1 <= remainder) && (remainder <= 5)) 修改为 (remainder <= 5) 效果相同
C.else if ((6 <= remainder) && (remainder <= 8)) 写法错误,应修改为 else if (6 <= remainder <= 8)
D.根据题意 remainder = N % 10 应修改为 remainder = N / 10
展开:答案、思考步骤与易错点
正确答案A
先这样想
先确定除法的商和余数分别代表什么,再代入小样例检查。
分步推导
- 每 10 个球颜色循环一次,所以用 `N % 10` 取出当前编号在这一组中的位置是对的基础。
- 前两个条件已经覆盖了余数 1 到 8,剩下只可能是 9 或 0,因此最后一个分支写成 `else` 与写成 `else if ((remainder == 9) || (remainder == 0))` 效果相同。
- B 会把余数 0 也判成 Red,C 的连续比较不是 C++ 里判断区间的正确写法,D 用除法得不到组内位置。
计算 / 追踪提示
计算时分清 `/` 是商,`%` 是余数;如果题目要求第 N 个位置,常要先改成从 0 开始的下标。
易错点
余数为 0 代表这一组的第 10 个位置,不要漏掉。
逻辑表达式取模运算条件筛选
下面C++代码执行后,将输出能被2整除且除以7余数为2的数。下列选项不能实现的是()。
for (int i = 0; i < 100; i++)
if (_____)
cout << i << " ";
A.((i % 2 == 0) && (i % 7 == 2))
B.((!(i % 2)) && (i % 7 == 2))
C.((!(i % 2)) && (!(i % 7)))
D.((i % 2 != 1) && (i % 7 == 2))
展开:答案、思考步骤与易错点
正确答案C
先这样想
先确定除法的商和余数分别代表什么,再代入小样例检查。
分步推导
- 题目要求同时满足“能被 2 整除”和“除以 7 余 2”。
- A 直接判断这两个条件;
- B 中 `!(i % 2)` 等价于 `i % 2 == 0`;
- D 中 `i % 2 != 1` 对整数也等价于偶数判断,所以 A、B、D 都能实现。
- C 的后半部分 `!(i % 7)` 表示 `i % 7 == 0`,筛出来的是 7 的倍数,不是“余 2”,因此它不能实现。
计算 / 追踪提示
建议在草稿纸画三列:当前变量、条件真假、本轮输出。遇到 continue 直接跳到下一轮,遇到 break 只跳出当前循环。
易错点
`!(i % 7)` 表示余数为 0,不是“余数不等于 0”。
阶乘递推算法效率比较
在数学中N!表示N的阶乘,即1到N的乘积,如3!=1*2*3,且0!=1。下面的两段C++代码用于求1到N的阶乘之和,如N为3,则结果是9(1!+2!+3!的值)。选项中的说法正确的是( )。
// 实现1
int i, N;
cin >> N;
int tnt = 0, last = 1;
for (i = 1; i < N + 1; i++) {
last *= i;
tnt += last;
}
cout << tnt << endl;
// 实现2
int i, N;
cin >> N;
int tnt = 0, tmp;
for (i = 1; i < N + 1; i++) {
tmp = 1;
for (int j = 1; j < i + 1; j++) {
tmp *= j;
tnt += tmp;
}
cout << tnt << endl;
}
A.虽然实现1的代码短小,但效率并不高
B.实现2的代码效率更高,且更易于理解
C.实现1因为应用了前项计算结果,计算量更小,因此效率高
D.两种实现,效率几乎一致
展开:答案、思考步骤与易错点
正确答案C
分步推导
- 实现 1 用变量 `last` 保存上一轮已经算出的阶乘。
- 若上一轮 `last = (i-1)!`,这一轮只需再乘一次 `i` 就得到 `i!`,然后累加到 `tnt`。
- 实现 2 对每个 `i` 都从 1 重新连乘到 `i`,乘法次数明显更多,因此效率更低。
- 于是“实现 1 因为应用了前项计算结果,计算量更小,因此效率高”是正确说法,选 C。
计算 / 追踪提示
建议在草稿纸画三列:当前变量、条件真假、本轮输出。遇到 continue 直接跳到下一轮,遇到 break 只跳出当前循环。
易错点
代码更短不一定只是书写简洁,很多时候也意味着重复计算更少。
嵌套循环布尔表达式反例判断
哥德巴赫猜想是指大于2的偶数都可以分解为两个质数之和,下面的代码用于验证4-1000之内的偶数能否分解为两个质数之和。下面C++代码中假设isPrime()是已经定义好用于判断正整数N是否为质数,返回bool值。对该段代码,错误的说法是( )。
for (i = 4; i < 1000; i += 2)
for (j = 2; j < i; j++)
if (isPrime(j) && isPrime(i - j)) {
printf("%d=%d+%d\n", i, j, i - j);
break;
}
A.将代码 isPrime(j) && isPrime(i-j) 修改为
isPrime(j) == true && isPrime(i-j) == true 效果相同
B.代码执行后,输出的一对质数,一定是小的数在前
C.即便将外层循环中i的上界1000修改为很大的整数,也不能说从数学上证明了哥德巴赫猜想
D.根据题意,break语句应该移到if语句块之外
展开:答案、思考步骤与易错点
正确答案D
先这样想
先列变量每轮变化,再看输出语句是否真的执行。
分步推导
- 代码的作用是:对每个偶数 `i`,从小到大枚举 `j`,一旦找到 `j` 和 `i-j` 都是质数,就输出这一组分解并停止当前内层循环。
- `break` 必须放在 `if` 语句块里,只有找到一组合法分解时才该停止;
- 若挪到 `if` 外面,内层循环会被过早终止,题意就被破坏,所以 D 是错误说法。
- A 只是把布尔值显式写成与 `true` 比较,效果相同;
- B 中 `j` 从小到大枚举,第一次找到的分解一定是较小的那个数在前;C 只是在有限范围内验证,不能当作数学证明。
计算 / 追踪提示
建议在草稿纸画三列:当前变量、条件真假、本轮输出。遇到 continue 直接跳到下一轮,遇到 break 只跳出当前循环。
易错点
“验证很多个例子”不等于“证明对所有情况都成立”。
循环输出赋值等价变形
已知 C++ 代码和执行后的期望输出如下,相关说法正确的是()。
int i, j, last, N;
cout << "请输入层数N:";
cin >> N;
last = 1;
for (i = 1; i < N; i++) {
for (j = 1; j < i + 1; j++) { //L1
if (last > 9)
last = 1;
cout << last << " ";
last += 1;
}
printf("\n");
}
1 请输入层数N:10
2 1
3 2 3
4 4 5 6
5 7 8 9 1
6 2 3 4 5 6
7 7 8 9 1 2 3
8 4 5 6 7 8 9 1
9 2 3 4 5 6 7 8 9
10 1 2 3 4 5 6 7 8 9
A.倒数第二行的 printf("\n") 有错,应该修改为 cout << endl;printf()函数不能输出换行
B.last += 1 修改为 last = last + 1 执行效果相同
C.代码中L1标记行中的 j < i + 1 应修改为 j < i
D.外层for循环前的 last = 1 修改为 last = 0 执行效果相同
展开:答案、思考步骤与易错点
正确答案B
先这样想
先列变量每轮变化,再看输出语句是否真的执行。
分步推导
- 这段程序按顺序输出从 1 到 9 循环出现的数字,`last += 1` 与 `last = last + 1` 是完全等价的写法,所以 B 正确。
- A 错在 `printf("\n")` 本来就能输出换行;
- C 若把 `j < i + 1` 改成 `j < i`,每行会少输出一个数;
- D 若把 `last` 初值改成 0,第一行就会先输出 0,结果显然不同。
计算 / 追踪提示
建议在草稿纸画三列:当前变量、条件真假、本轮输出。遇到 continue 直接跳到下一轮,遇到 break 只跳出当前循环。
易错点
判断“效果是否相同”时,要代入示例输出逐行核对,而不是只看某一行代码长得像不像。
变量交换赋值语句
下面C++执行后将输出3*2=6。()
int a = 2, b = 3;
a = a - b;
b = a + b;
a = b - a;
printf("%d*%d=%d\n", a, b, a * b);
判断本题结论:先独立判断,再展开答案。正确答案是 正确。
展开:答案、思考步骤与易错点
正确答案正确
先这样想
把题干拆成两半:事实是否正确,结论是否被事实支持。
分步推导
- 初始 `a=2`,`b=3`。
- 执行 `a = a - b` 后 `a=-1`;
- 执行 `b = a + b` 后 `b=2`;
- 执行 `a = b - a` 后 `a=3`。
- 于是最后 `a` 和 `b` 互换成功,`printf` 输出的是 `3*2=6`,所以题干说法正确。
计算 / 追踪提示
计算时分清 `/` 是商,`%` 是余数;如果题目要求第 N 个位置,常要先改成从 0 开始的下标。
易错点
这三句并不是随便改值,而是在不借助第三个变量完成交换。