题目背景

对应的选择、判断题:试题 - GESP 202412 C++ 四级 - 洛谷有题

题目描述

小杨最近发现了有趣的 Recamán 数列,这个数列是这样生成的:

  • 数列的第一项 a1​ 是 1;
  • 如果 ak−1​−k 是正整数并且没有在数列中出现过,那么数列的第 k 项 ak​ 为 ak−1​−k,否则为 ak−1​+k。

小杨想知道 Recamán 数列的前 n 项从小到大排序后的结果。手动计算非常困难,小杨希望你能帮他解决这个问题。

输入格式

第一行,一个正整数 n。

输出格式

一行,n 个空格分隔的整数,表示 Recamán 数列的前 n 项从小到大排序后的结果。

输入输出样例

输入 #1复制

5

输出 #1复制

1 2 3 6 7

输入 #2复制

8

输出 #2复制

1 2 3 6 7 12 13 20

说明/提示

样例解释

对于样例 1,n=5:

  • a1​=1;
  • a1​−2=−1,不是正整数,因此 a2​=a1​+2=3;
  • a2​−3=0,不是正整数,因此 a3​=a2​+3=6;
  • a3​−4=2,是正整数,且没有在数列中出现过,因此 a4​=a3​−4=2;
  • a4​−5=−3,不是正整数,因此 a5​=a4​+5=7。

a1​,a2​,a3​,a4​,a5​ 从小到大排序的结果为 1,2,3,6,7。

数据范围

对于所有数据点,保证 1≤n≤3000。

代码实现:

#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<int> seq;
    unordered_set<int> vis;
    seq.push_back(1);
    vis.insert(1);
    for(int k=2;k<=n;k++)
    {
        int prev=seq.back();
        int sub=prev-k;
        if(sub>0&&!vis.count(sub))
        {
            seq.push_back(sub);
            vis.insert(sub);
        }
        else
        {
            int add=prev+k;
            seq.push_back(add);
            vis.insert(add);
        }
    }
    sort(seq.begin(),seq.end());
    for(int i=0;i<seq.size();i++)
    {
        if(i>0) cout<<" ";
        cout<<seq[i];
    }
    return 0;
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐