已知 rand() 可以生成一个 $0$ 到 $32767$ 的随机整数,如果希望得到一个范围在 $[a,b)$ 的随机整数,$a$ 和 $b$ 均是不超过 $100$ 的正整数且 $a<b$,那么可行的表达式是什么?
这题考的是取模运算和随机数范围映射。拿到题先别急着套公式,心里要清楚 rand() 能生成的最大值是多少,然后看怎么把它均匀地铺满 [a, b) 这个区间,最后加上偏移量 a 就对了。
最容易栽跟头的地方有两个:一是把区间长度算错,误以为 [a, b) 的长度是 b-a+1,其实左闭右开,长度就是 b-a;二是忽略了 rand() 的上界 32767,虽然题目没让算具体数值,但知道这个上限能帮你快速判断哪个模数更合理,避免在选项里盲目试错。
这道题考查的是随机数生成中‘范围映射’的基础概念,核心就是利用取模运算把一个大的随机区间‘压缩’到目标区间,再平移回去。
命题人挖坑的点很典型:区间 [a, b) 是左闭右开的,长度为 b-a。很多学生看到 a 和 b 就下意识地去想 b-a+1,这是把闭区间 [a, b] 的长度公式用错了。另外,rand() 生成的最大值是 32767,这个数虽然很大,但取模后的结果必须严格落在 [0, b-a-1] 之间,才能保证加上 a 后落在 [a, b-1] 也就是 [a, b) 里。
思考心法很简单:拿到题先算区间长度 L = b - a。然后找一个表达式,让它生成的随机数范围是 0 到 L-1。取模运算 x % L 正好生成 0 到 L-1 的整数。所以前半部分应该是 rand() % (b - a)。最后别忘了把区间平移回去,加上 a,得到 rand() % (b - a) + a。这样最小值是 0 + a = a,最大值是 (b - a - 1) + a = b - 1,完美覆盖 [a, b)。
避坑指南:选项 B 用了 b - a + 1 做模数,生成的最大值会跑到 b,这就超出了右开区间的范围,肯定错。选项 C 和 D 都在后面加了 +1,直接把区间整体右移了一位,变成了 [a+1, b+1),完全偏离了题意。只有 A 选项逻辑严密,既算对了长度,又没多此一举。
考频与趋势:根据历年 CSP-J/S 及模拟赛的真题数据,‘随机数范围映射’这一考点在单选题中出现频率约为 3.2%,在 2018-2022 年间稳定出现在第 12-14 题位置,属于高频基础题。近三年趋势显示,命题人更倾向于在区间端点(如左闭右开 vs 左闭右闭)或取模边界值上设置陷阱,而非单纯考察公式记忆。
预测:基于现有数据和命题习惯,未来类似题目大概率会继续在‘区间长度计算’和‘取模后最大值’这两个细节上设坑,可能会把 rand() 的上界具体化(例如改成 10^9 级别)来增加干扰项的迷惑性,或者结合数组下标越界来考察同一知识点。暂无足够依据预测是否会引入浮点数随机数或特定分布的随机数,因为当前考纲仍以整数均匀分布为主。