[12月考试] F
[12月考试] F
题目描述
有 nnn 个人围成一个环,从第 111 个人开始进行共 n−1n-1n−1 次报数。
第 iii 次报数开始的人报 111,接着右边的人依次报 2,3,…2,3,\ldots2,3,…,报到 aia_iai 结束,报到 aia_iai 的人退出这个环,从这个人右边第一个人开始第 i+1i+1i+1 轮报数。
求 n−1n-1n−1 轮报数结束后剩下的人的编号。
对于所有数据,n≤1000n\leq 1000n≤1000,1≤ai≤1091\leq a_i\leq 10^91≤ai≤109。
输入格式
输入共 222 行。
第 111 行输入 111 个正整数 nnn。
第 222 行输入 n−1n-1n−1 个正整数 a1,a2,…,an−1a_1,a_2,\ldots,a_{n-1}a1,a2,…,an−1。
输出格式
输出共 111 行 111 个数,表示答案。
样例 #1
样例输入 #1
7
3 4 2 3 1 2
样例输出 #1
4
提示
样例解释 1
退出的顺序为:3,7,2,6,1,53,7,2,6,1,53,7,2,6,1,5。
数据范围
对于 30%30\%30% 的数据,n,ai≤5n,a_i\leq 5n,ai≤5。
对于 60%60\%60% 的数据,n,ai≤20n,a_i\leq 20n,ai≤20。
对于 80%80\%80% 的数据,n,ai≤100n,a_i\leq 100n,ai≤100。
对于所有数据,n≤1000n\leq 1000n≤1000,1≤ai≤1091\leq a_i\leq 10^91≤ai≤109。
🧠 问题理解
有 nnn 个人围成一个环,每轮报数从某个人开始,报数到第 aia_iai 个数字的那个人出局,下一轮报数从被淘汰者右边的第一个人开始。共进行 n−1n-1n−1 轮,最后剩下一个人,求该人的编号。
✅ 解题思路
- 模拟环状队列: 用一个数组或链表维护剩余的人的编号。
- 当前起始位置索引: 记录每轮报数开始的位置。
- 报数位置计算:
报数到第 aia_iai 个,实际上是从当前起始位置往右数 (ai−1)mod 当前人数(a_i - 1) \mod \text{当前人数}(ai−1)mod当前人数 步。 - 删除该人: 将该人从队列中移除。
- 更新起始位置:
下一轮从被淘汰者右边的第一个人开始,更新起始位置索引。 - 重复进行 n−1n-1n−1 轮后,队列中只剩一个人,即答案。
🚀 C++实现
#include <iostream>
using namespace std;const int MAXN = 1000;
int people[MAXN];int main() {int n;cin >> n;int a[MAXN];for (int i = 0; i < n - 1; ++i) {cin >> a[i];}// 初始化编号数组,0-based 方便处理for (int i = 0; i < n; ++i) {people[i] = i + 1; // 1-based 编号}int size = n;int start = 0; // 起始报数位置for (int i = 0; i < n - 1; ++i) {// 报数位置 = (start + a[i] - 1) % 当前人数int pos = (start + a[i] - 1) % size;// 淘汰people[pos]// 删除元素:后面的往前移动覆盖for (int j = pos; j < size - 1; ++j) {people[j] = people[j + 1];}size--;// 下一轮报数从淘汰者右边的人开始,实际上是当前位置不变(因为淘汰者后面元素已左移覆盖)start = pos % size;}// 剩下最后一个人cout << people[0] << endl;return 0;
}