https://pintia.cn/problem-sets/994805260223102976/problems/994805320306507776
2021.3.8改进版本
一开始一边输入一边找关键数,但是发现不行,必须是全部输入完成后再找出关键数。
#include<iostream>
#include<algorithm>
using namespace std;
int cover[100000]={0};
bool cmp(int a, int b){
return a > b;
}
int main(){
int n, t;
cin >> n;
int num[n], res[n], k=0;
for(int i=0; i<n; i++){
cin >> num[i];
t = num[i];
// 标记覆盖数
while(t != 1){
if(t%2 != 0){
t = 3*t+1;
}
t /= 2;
// 已经标记过,后面就跳过了
if(cover[t]==1){
break;
}
cover[t] = 1;
}
}
// 从输入的数中找出没被覆盖的数,即关键数
for(int i=0; i<n; i++){
if(cover[num[i]]==0){
res[k++] = num[i];
}
}
// 从大到小排序
sort(res, res+k, cmp);
// 输出
for(int i=0; i<k; i++){
cout << res[i];
if(i<k-1)
cout << " ";
}
return 0;
}
2021.1.31日版本
回顾一下1001的题:
对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1。
这个题不一样的是,输入n个数,如:3、5、6、7、8、11,遍历每个数,
对于m=3,每一步得到的数分别为10、5、8、4、2,这些数被称为覆盖数;
对于m=7,覆盖数为11、17、26、13、20、10(5、8、4、2),括号内不用算了;
对于m=5、m=8和m=11,因为它已经是覆盖数所以不用再计算了;
所以m=6和m=7没被任何数覆盖,它们被称为关键数。
这道题就是要求一串数字中的关键数。
#include<iostream>
using namespace std;
int num[10000], cover[10000];
void addCover(int n){
while(n!=1){
// 数处理
if(n % 2 == 0)
n /= 2;
else
n = ((n*3)+1)/2;
// 如果覆盖数里面没有这个数,把这个数加入到覆盖数
if(cover[n] == 0 && n <= 100){
cover[n] = n;
if(num[n] == n)
num[n] = 0;
}else if(cover[n] != 0){
break;
}
}
}
int main(){
int n, m, max = -1, flag = 0;
cin >> n;
for(int i=0; i<n; i++){
cin >> m;
if(m > max)
max = m;
num[m] = m;
// 如果覆盖数里面没有这个数,添加它的覆盖数进行处理
if(cover[m]==0){
addCover(m);
}else{
num[m] = 0;
}
}
// 输出
for(int i=max; i>=0; i--){
if(num[i] == 0) continue;
if(flag > n) break;
if(flag > 0)
cout << " ";
cout << num[i];
flag ++;
}
return 0;
}
最开始的时候会报两个段错误,因为数组越界,所以把两个数组的个数扩大100倍。
后面又报了一个答案错误,因为 n = ((n*3)+1)/2 时,忘记除以2了,但是为什么还是有四个点通过了呢,因为它还是会在下一次循环的时候除以2。
最后终于通过了,哈哈!谢谢男朋友帮忙~