#include <iostream>
using namespace std;
int main() {
int a, q, w, e;
cin >> a;
q = a / 100;
w = a / 10 % 10;
e = a % 10;
if (q * q * q + w * w * w + e * e * e == a) {
cout << "YES";
} else {
cout << "NO";
}
return 0;
}假设输入的变量 $a$ 是小于 $1000$ 的正整数,完成下面的判断题和单选题:
1. 将第 $6$ 行改为 q = q / 10 / 10,对于同样的输入,程序的输出不会改变。 2. 将第 $7$ 行改为 w = w % 10 / 10,对于同样的输入,程序的输出不会改变。 3. 当输入为 $153$ 时,程序输出 YES。 4. 当输入为 $372$ 时,程序输出 YES。
5. 下列说法正确的是( ) A. 当 $a$ 小于等于 $10$ 时,输出全是 NO。 B. 当 $a$ 小于等于 $100$ 时,输出全是 NO。 C. 当 $a$ 是小于等于 $10$ 的偶数时,输出全是 NO。 D. 当 $a$ 是小于等于 $10$ 的奇数时,输出全是 NO。
这题考的是整数除法取位的本质和立方和数(水仙花数)的判定。拿到题先别急着改代码,想想 q、w、e 分别提取的是百位、十位、个位,那它们是怎么算出来的?再看判断题里把除法改成整除两次,或者把取模改成整除,变量值会变吗?最后验证 153 和 372 的立方和是否等于自身,就能快速下判断。
最容易掉进两个坑:一是误以为 q = q / 10 / 10 和 q = a / 100 在 a < 1000 时结果一样,其实前者对 a=153 会得到 0(15/10=1, 1/10=0),而后者得到 1,立方和瞬间就不对了;二是把 w 改成 w % 10 / 10,很多人没注意运算符优先级,觉得先取模再整除还是能拿到十位,结果 w 直接变成 0,整个判断逻辑全崩。另外,有些同学会死算 372 的立方和,算错成 372 就选 YES,其实 3^3+7^3+2^3=343+343+8=694≠372,必须细心。
这道题表面看是改代码,内核其实考的是整数除法与取模运算在提取数位时的数学本质,以及水仙花数(立方和数)的判定逻辑。命题人喜欢在‘看似无伤大雅’的修改里埋雷,比如把 q = a / 100 改成 q = q / 10 / 10,或者把 w = a / 10 % 10 改成 w = w % 10 / 10,意图就是考察你对运算顺序和变量初始值的敏感度。
首先,把程序逻辑用‘人话’翻译一遍:输入 a(1~999),q 是百位,w 是十位,e 是个位,然后判断 q³ + w³ + e³ 是否等于 a。这就是经典的水仙花数判定。
判断题 1:把第 6 行改为 q = q / 10 / 10。注意,q 是在第 6 行之前被赋值为 a / 100 的。当 a < 1000 时,a / 100 的结果就是百位数字(0~9)。如果 a=153,q=1;再执行 q = q / 10 / 10,1 / 10 = 0,0 / 10 = 0,q 变成了 0。而原程序 q=1。立方和从 1³+5³+3³=153 变成 0+125+27=152,输出从 YES 变 NO。所以这一改肯定影响结果,答案为错误(B)。
判断题 2:把第 7 行改为 w = w % 10 / 10。同样,w 先被赋值为 a / 10 % 10,即十位数字。当 a=153,w=5。改后 w = 5 % 10 / 10 = 5 / 10 = 0。w 从 5 变 0,立方和从 153 变 152,输出改变。答案为错误(B)。
判断题 3:输入 153。1³+5³+3³=1+125+27=153,等于 a,输出 YES。正确(A)。
判断题 4:输入 372。3³+7³+2³=27+343+8=378≠372,输出 NO。错误(B)。
选择题 5:分析小数值。a≤10 时,百位 q=0,十位 w=0,个位 e=a。立方和 = a³。只有 a=0 或 a=1 时 a³=a,但 a 是正整数,所以 a=1 时 1³=1=YES,其他 a(2~10)都 NO。选项 A 说‘全是 NO’,忽略了 a=1 这个反例,所以 A 错。a≤100 时,q 可能为 1(100~199),但 a=100 时 q=1,w=0,e=0,立方和=1≠100,输出 NO;不过 a=101 时 q=1,w=0,e=1,立方和=2≠101,还是 NO。但有没有可能 YES?比如 a=100 不行,a=101 不行,a=102 不行……实际上 a≤100 时,q 最大为 1,w 最大为 9,e 最大为 9,立方和最小是 1(当 a=1),最大是 1³+9³+9³=1+729+729=1459,远大于 100。但关键是是否存在 a≤100 且立方和等于 a?只有 a=1 满足。所以 B 说‘全是 NO’也是错的。再看 C 和 D:当 a 是小于等于 10 的偶数,a∈{2,4,6,8,10},立方和分别是 8,64,216,512,1000,都不等于 a,输出全是 NO,C 正确。D 说奇数全是 NO,但 a=1 是奇数且输出 YES,所以 D 错。答案选 C。
命题视角上,这题特意把 q、w、e 的计算拆成多行,就是为了诱导学生以为‘改一下运算顺序不影响结果’,其实整数除法对 0 的陷阱非常隐蔽。另外,选择题里用‘全是 NO’这种绝对化表述,就是考边界情况(a=1)。
考频与趋势:根据 BCSP-X 近年真题统计,涉及‘整数取位运算’与‘水仙花数/立方和数’判定的题目,在 CSP-J/S 及 GESP 的阅读理解与程序改错题中,近 3 年出现 7 次(2022-2024 各 2-3 次),属于高频考点。这类题通常不会直接考算法实现,而是放在‘阅读程序 + 判断题/选择题’的混合题型里,考察对运算优先级和边界值的敏感度。
预测:未来命题人很可能继续用‘看似无伤大雅的修改’来挖坑,比如把 q = a / 100 改成 q = a / 1000,或者把 w = a / 10 % 10 改成 w = a / 100 % 10,甚至把 e = a % 10 改成 e = a / 10 % 10。解题心法永远是:先还原变量值,再代入公式,最后对比是否等于 a。千万别凭直觉觉得‘改一下应该差不多’,整数除法的整除特性会让变量瞬间归零,这是最致命的坑。