华数杯中真题中的程序题

"双减"的口号喊了一遍遍,可是学生们的竞争压力一点没减少,而且越来越卷。最近孩子妈给孩子找了些数学思维的题目,据说是华数杯的真题,想帮助孩子提高提高数学。她看了一下题目说看不懂,问我会不会。我一瞧,这数学题目里怎么是个编程题?感觉就编程来说不是太难,但是要用数学方法解,我还真是直挠头。于是我觉得还是先把程序写出来,如果你有这方面的经验,还烦请指教

第一题

将任意两个正整数 a 和 b 依次输入到程序中,程序将按照以下步骤执行:

步骤 1:

令 q 的值为 0;

步骤 2:

当 a<b 时,依次输出 q 和 a 的值,结束整个程序;

否则将原来的 a 替换为 a–b 作为 a,并且将 q 的值增加 1 作为 q;

当 a–b<b 时,依次输出 q 和 a,否则重复执行步骤 2. 现在向程序依次输入正整数 122 和 7,

请问:程序输出的 q 的值是__________,a 的值是__________.

看了题干,感觉直接按文字写成代码就行了,我也只会写个 js,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let q = 0;
function calc(a, b) {
if (a < b) {
console.log(q, a);
return;
} else {
a = a - b;
q = q + 1;
// if (a - b < b) {
if (a < b) { // 2023-03-20 补:题目中的 a - b < b 实际上是迷惑项,此处不用判断,因为上一个逻辑中已经判断过一遍
console.log(q, a);
return;
} else {
calc(a, b);
}
}
}

calc(122, 7);

最后输出的结果是 q = 16a = 10,也不清楚对不对。

输入结果是 q = 17a=3

到网上搜了一下,在 2021 的华数杯中有 类似的一题

将任意两个正整数a和b依次输入到程序中,程序将按照以下步骤执行: 步骤 1:令q的值等于 0; 步骤 2:当a小于b时,依次输出q和a的值,结束整个程序;否则将a的值减去b, 并且将q的值增加 1,重复执行步骤 2. 现在向程序依次输入正整数 122 和 7,请问程序输出q的值是______,a的值是_____

这题比上面的题目少一个条件,答案解析是这么写的:

这个程序是用减法来实现带余数除法. 输入的 a 和 b 依次为被除数和除数, 每次将被除数减去除数,如果够减,q 的值加 1,直到不够减为止. 此时输出的 q 为带余数除法的商, 而 a 为余数.若输入 a = 122 和 b = 7,由带余除法 122 ÷ 7 = 17 … 3 可知输出的 q = 17, a = 3

于是简化一下之前的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
let q = 0;
function calcb(a, b) {
if (a < b) {
console.log(q, a);
return;
} else {
a = a - b;
q = q + 1;
calcb(a, b);
}
}

calcb(122, 7);

最终输出的结果是 17 和 3,与答案一致。

正如答案解析所述,这题实际上考察的是对除法的认知

题目二

将任意一个大于 0 小于 100 的一位小数(即小数点后有一位的数)x 输入到程序中, 程序都将按照以下步骤执行:

步骤 1:

令 y 的值等于 x 乘以 10 的积;

令 p 的值等于 y 除以 10 的商;

令 q 的值等于 y 除以 10 的余数;

步骤 2:

如果 q 大于 4,则将 p 的值加 1;

步骤 3:

输出 p,结束整个程序.

现在将一位小数 21.6 输入到程序中,则程序输出的 p 的值是__________.

这一题也是直接按照题干写代码:

1
2
3
4
5
6
7
8
9
10
11
12
function calc(x) {
let y = x * 10;
let p = y / 10; // 这里比较奇怪,按上面的逻辑 p === x 了
let q = y % 10;
if (q > 4) {
p = p + 1;
}
console.log(p);
return;
}

calc(21.6);

最终输出 p = 22.6,找了一下 答案解析 答案是 2222.6

输入21.6,y=216,216÷10=21...6,商=21,余数=6,余数大于4,则商+1,商=22

我感觉这里的差异在于对 的解释是否包含小数位,如果不包含的话,程序就改成:

1
2
3
4
5
6
7
8
9
10
11
12
function calc(x) {
let y = x * 10;
let p = Math.floor(y / 10);
let q = y % 10;
if (q > 4) {
p = p + 1;
}
console.log(p);
return;
}

calc(21.6);

这样结果就是 22

由上面可以看出,这题考察的实际上是对四舍五入的实现认知

对于这样的数学题,我感觉真的有点牵强附会,似乎是想把孩子们训练成 《沙丘》 里的 “门泰特”。这样的题目以及对应的教学没有教会孩子编程思维,而是把孩子们当作计算机本身去模拟计算机的行为,这是不是有点本末倒置?