PAT乙级1005

题目链接

https://pintia.cn/problem-sets/994805260223102976/problems/994805320306507776

题解

题意很简单,我并没有理解错,但刚开始最后一个测试点过不了。

代码逻辑检查多次后问了室友,说是isKey数组会越界,因为在callatz(n)中使用了isKey[n],这个n由于n=(3*n+1)/2导致n的范围变化,不再是小于100。

我真的呜了……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// PAT BasicLevel 1005
// https://pintia.cn/problem-sets/994805260223102976/problems/994805320306507776
#include <iostream>
#include <algorithm>
using namespace std;

#define N 310 // 数组大小
bool isKey[N]; // N个数字是否为关键数:isKey[i]==true,则i是关键数;否则i不是关键数
bool isValid[N]; // N个数字是否被用户输入:isValid[i]==true,则i已被用户输入;否则i未被用户输入
void callatz(int n); // 循环处理isKey[n]:n若被覆盖,则不必往下计算,函数结束;若n未被覆盖,则覆盖n并按规则更新n。循环以上过程

int main()
{
// 默认N个数字都未被覆盖,即N个数字是关键数
fill(isKey, isKey + N, true);

// 记录k个正整数n;对于每个正整数n,调用callatz()函数(用户输入的正整数n,并不会被自己覆盖,所以传参时直接将n更新)
int k, n;
scanf("%d", &k); // k个整数
for (int i = 0; i < k; ++i)
{
scanf("%d", &n);
isValid[n] = true; // 记录用户输入的正整数n
callatz(n % 2 == 0 ? n / 2 : (3 * n + 1) / 2);
}

// 输出结果
bool isFirstKey = true;
for (int i = N - 1; i >= 0; --i)
{
if (isValid[i] && isKey[i])
{
if (isFirstKey)
{
printf("%d", i);
isFirstKey = false; // 输出第一个关键数后,之后输出的关键数就不是第一个关键数了
}
else
{
printf(" %d", i);
}
}
}

system("pause");
return 0;
}

void callatz(int n)
{
while (n != 1)
{
// n未被覆盖
if (isKey[n])
{
// 将n覆盖
isKey[n] = false;

// 按照规则更新n
if (n % 2 == 0)
{
n = n / 2;
}
else
{
n = (3 * n + 1) / 2;
}
}
// n已被覆盖,不必往下计算
else
{
break;
}
}
}

作者:@臭咸鱼

转载请注明出处:https://www.cnblogs.com/chouxianyu/

欢迎讨论和交流!