2 条题解
-
0
这是一份经过验证的、可以直接提交的 C++ 参考代码。
解题思路回顾
- 找排名:首先将所有人的成绩从大到小排序,找到小 R 的成绩排在第几名(记为
rank)。 - 定列号:每 个人填满一列,所以列号 。
- 定行号:
- 算出该考生是这一列的第几个填入的:
pos = (rank - 1) % n + 1。 - 奇数列(第 1, 3, 5...列):从上往下填(),所以行号 。
- 偶数列(第 2, 4, 6...列):从下往上填(),所以行号 。
- 算出该考生是这一列的第几个填入的:
参考代码 (C++)
#include <iostream> #include <vector> #include <algorithm> // 用于 sort using namespace std; int main() { // 优化输入输出效率(虽数据量小,但养成好习惯) ios::sync_with_stdio(false); cin.tie(0); int n, m; if (!(cin >> n >> m)) return 0; // 总人数 int total = n * m; // 使用 vector 存储所有成绩 vector<int> scores(total); int my_score = -1; // 用于记录小 R 的成绩 for (int i = 0; i < total; ++i) { cin >> scores[i]; // 第一个输入的成绩是小 R 的 if (i == 0) { my_score = scores[i]; } } // 1. 将成绩从大到小排序 // 使用 greater<int>() 实现降序排序 sort(scores.begin(), scores.end(), greater<int>()); // 2. 找到小 R 的排名 (从 1 开始) int rank = -1; for (int i = 0; i < total; ++i) { if (scores[i] == my_score) { rank = i + 1; // 下标是从0开始的,排名要+1 break; } } // 3. 计算列号 c // 公式逻辑:每 n 个人一列,向上取整 int c = (rank - 1) / n + 1; // 4. 计算行号 r // 先算出他在这一列是“第几个”放进去的 int pos = (rank - 1) % n + 1; int r; if (c % 2 != 0) { // 奇数列 (1, 3, 5...):从上往下填 (1 -> n) // 所以位置就是行号 r = pos; } else { // 偶数列 (2, 4, 6...):从下往上填 (n -> 1) // 比如 n=4,第1个放进去的在第4行,第2个在第3行... // 公式:n - pos + 1 r = n - pos + 1; } // 输出结果:列号 行号 cout << c << " " << r << endl; return 0; }代码关键点解析
sort(..., greater<int>()):这是标准库提供的降序排序写法,比自己写 cmp 函数更方便。(rank - 1) / n + 1:这是计算“当前在第几组(第几列)”的经典数学公式,等同于 (向上取整)。c % 2 != 0:判断列号的奇偶性,是解决“蛇形”走向的关键。
- 找排名:首先将所有人的成绩从大到小排序,找到小 R 的成绩排在第几名(记为
-
0
你好!这是 CSP-J 2025 的一道模拟/数学题。题目虽然描述了“蛇形”排列,看起来有点绕,但只要分步拆解,逻辑其实很清晰。
这里给你提供解题的几个关键步骤提示:
1. 第一步:确定排名(我是第几名?)
题目说座位是按照“第一轮成绩由高到低”分配的。 这意味着你需要知道小 R 的成绩在所有考生中排第几。
- 方法:
- 读入数据时,先把小 R 的成绩(也就是输入的第一个数 )专门存到一个变量里,比如叫
my_score。 - 把所有考生的成绩数组进行从大到小排序(可以使用
sort配合greater<int>())。 - 遍历排序后的数组,找到
my_score在其中的位置(下标)。记这个排名为 (注意:题目通常说第 1 名,所以如果是 0-based 下标,记得加 1)。
- 读入数据时,先把小 R 的成绩(也就是输入的第一个数 )专门存到一个变量里,比如叫
2. 第二步:确定列号(我在第几列?)
座位是先填满第 1 列,再填满第 2 列…… 这样一列一列填的。 每一列有 个座位。
- 假设你的排名是 。
- 你可以想象把人按顺序分组,每 个人一组。
- 公式推导:
- 第 名在第 1 列。
- 第 名在第 2 列。
- ...
- 列号 。在 C++ 整数运算中,可以写成
(K - 1) / n + 1。
3. 第三步:确定行号(我在该列的第几行?)
这是题目唯一的难点:蛇形分布。 你需要判断当前列是奇数列还是偶数列,因为它们的填充方向不同。
- 首先,算出你在这一列是“第几个”填入的。
- 位置
pos = (K - 1) % n + 1。
- 位置
- 分类讨论:
- 奇数列(1, 3, 5...):题目描述是“从第 1 行到第 行”(从上往下)。
- 这时,行号 就是
pos。
- 这时,行号 就是
- 偶数列(2, 4, 6...):题目描述是“从第 行到第 1 行”(从下往上,倒着填)。
- 这时,行号 应该是倒过来的位置。想一想,如果总共 行,第 1 个填入的人其实在第 行,第 2 个在第 行...
- 公式是:。
- 奇数列(1, 3, 5...):题目描述是“从第 1 行到第 行”(从上往下)。
4. 数据范围提示
注意看数据范围:。 这是一个非常非常小的数据。 这意味着:
- 你完全可以使用最朴素的排序和遍历。
- 甚至,如果你不想推导数学公式,你可以直接开一个二维数组
map[15][15],写个双重循环按照蛇形走位把所有名次填进去,最后遍历查找小 R 在哪里。这也是一种稳妥的满分做法。
代码逻辑框架
1. 输入 n, m 和所有成绩。 2. 记录 target = a[1]。 3. 对成绩数组进行降序排序。 4. 找到 target 在数组中的排名 K (从1开始)。 5. 计算列号 c = (K - 1) / n + 1。 6. 计算该列的相对位置 pos = (K - 1) % n + 1。 7. 判断 c 是奇数还是偶数: - 如果是奇数:r = pos - 如果是偶数:r = n - pos + 1 8. 输出 c 和 r。加油!这是一道非常标准的数学模拟题。
- 方法:
- 1
信息
- ID
- 19026
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- 3
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者