B4068 [GESP202412 四级] Recamán
欢迎报名洛谷网校,报名课程可以获得对应组别的知识点讲解与答疑服务,期待和大家一起进步!点击图片即可报名。
:::align{center} :::
本题考查桶思想和排序。
根据题目含义,先求出 Recamán 数列,使用数组 vis,如果 vis[x] == 1,说明 vis 数组应该开多少,后面会详细讨论这个问题。
因此我们可以写出下列计算 Recamán 数列的代码:
a[1] = vis[1] = 1;
for (int i = 2; i <= n; i++) {
if (a[i - 1] - i >= 1 && !vis[a[i - 1] - i])
a[i] = a[i - 1] - i;
else
a[i] = a[i - 1] + i;
vis[a[i]] = 1;
}
题目要求输出 Recamán 数列从小到大排序后的结果。由于数据范围中
for (int i = 1; i <= n; i++) {
int mx = a[i], id = i;
for (int j = i + 1; j <= n; j++) {
if (a[j] < mx) {
mx = a[j];
id = j;
}
}
swap(a[i], a[id]);
}
最后我们研究这个问题:记录这个数是否出现过的 vis 数组应该开多大呢?可以先将 vis 数组开得足够大(例如:vis 数组不需要开的非常大,只需开到
实际上使用简单的数学推理即可得出,vis 数组肯定不需要开得很大。首先,只有执行加法时,最大值才会更新。假设一种最坏的情况(且是必然不可能出现的情况):每一步都是执行加法,那么数列的第 vis 数组的大小会是一个天文数字。