题目描述:
题意简化:
覆盖的定义:将n按照卡拉兹猜想去递推,递推过程的数就是被n覆盖的数
给定一个序列,找出序列中那些没有被序列其他数字覆盖过的数,从大到小输出
思路分析:
- 对于序列中的每个数,按照卡拉兹猜想去递推,标记递推中出现过的数,表示这个数被覆盖过(因为每个数的大小是1~ 100,所以对于递推中大于100的数不用进行标记,因为序列中根本不会出现大于100的数)
- 因为要从到大到小输出,可以遍历一遍序列,将没有被标记过(即没有被序列其他数字覆盖过)的数加入vector,然后将vector里的数按照从大到小输出即可
- 注意输出格式,行尾不能输出空格。可以有两种方式解决:
①先输出第一个数,然后输出后面的数之前先输出一个空格
②如果不是输出最后一个数,就多输出一个空格
算法:
模拟
c++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int n;
int a[N],v[N]; // a[]存储序列,v[]存储每个数是否被标记过
vector <int> res; // res存储未被标记过的数
// 标记"x递推过程中被覆盖的数"
void solve(int x){
while(x != 1){
if(x % 2 == 0) x /= 2;
else x = (3 * x + 1) / 2;
if(x > 100) continue;
v[x] = 1;
}
}
int main(){
cin >> n;
// 对于序列中的每个数,按照卡拉兹猜想去递推,标记递推中出现过的数
for(int i = 0;i < n;i ++){
cin >> a[i];
solve(a[i]);
}
// 遍历一遍序列,将没有被标记过(即没有被序列其他数字覆盖过)的数加入vector
for(int i = 0;i < n;i ++)
if(!v[a[i]]) res.push_back(a[i]);
// 将vector里的数按照从大到小排序
sort(res.begin(),res.end(),greater<int>());
// 注意输出格式
cout << res[0];
for(int i = 1;i < res.size();i ++)
cout << ' ' << res[i];
puts("");
return 0;
}