PAT 乙级题目讲解:1005 《继续(3n+1)猜想》 📅 2026/7/4 8:52:40 ✅ PAT 乙级题目讲解1005《继续(3n1)猜想》摘要本题是 PAT 乙级 1005 题延续 1001 的 (3n1) 猜想。给定一组正整数需要找出那些没有出现在其他数字的验证路径中的“关键数”并按从大到小输出。解题核心在于用两个布尔数组分别记录原始输入和路径覆盖最后求差集。常见易错点包括遗漏原始标记、排序方向错误和输出末尾多余空格。 题目简介本题延续了 1001 题的“(3n1)猜想”但这次输入的是一组正整数任务是找出这些数中“关键数”即没有出现在其他数字的验证路径中的数。题目要求将所有关键数按从大到小的顺序输出。 样例分析输入6 3 5 6 7 8 11逐个分析每个数字的路径3 → 5 → 8 → 4 → 2 → 15 → 8 → 4 → 2 → 16 → 3 → 5 → 8 → 4 → 2 → 17 → 11 → 17 → 26 → 13 → 20 → 10 → 5 → …8 → 4 → 2 → 111 → 17 → …我们发现6与7的路径中包含了很多其它数字但6和7本身没有出现在其它数字的路径中 → 它们是关键数。因此输出为7 6 解题思路 关键变量说明变量名含义k输入的数字个数t当前读入并处理的数字a[]标记哪些数字是输入原始数字f[]标记哪些数字出现在路径中b[]存放筛选出的关键数本题的解决流程可以分为以下几个步骤✅ Step 1读入所有数字记录原始输入我们需要读入kkk个正整数标记每一个原始数字a[t] 1方便后续判断其是否为关键数。scanf(%d,k);while(k--){scanf(%d,t);a[t]1;// 标记为原始输入✅ Step 2对每个输入数字执行卡拉兹猜想路径变换如果是偶数tt/2t t / 2tt/2如果是奇数t(3∗t1)/2t (3 * t 1) / 2t(3∗t1)/2将整个路径中经过的数字全部标记在数组f[]中while(t!1){if(t%20)t/2;elset(3*t1)/2;f[t]1;// 出现在路径中}✅ Step 3筛选关键数关键数满足它是原始输入a[i] 1它没有出现在任何路径中f[i] 0我们按照从大到小的顺序枚举并输出这些数for(inti100;i1;i--){if(a[i]!f[i]){b[j]i;}}✅ Step 4输出格式控制注意数字之间用空格隔开末尾不带空格。for(inti1;ij;i){printf(%d,b[i]);if(ij)printf( );}完整代码#includebits/stdc.husingnamespacestd;intk,t;boolf[10005],a[105];intmain(){scanf(%d,k);while(k--){scanf(%d,t);a[t]1;// 标记 t 是数列中待验证数字while(t!1){if(t%20){t/2;}else{t(3*t1)/2;}f[t]1;// 标记验证路径中出现过的数字}}intb[105]{},j0;for(inti100;i1;i--){if(a[i]!f[i]){b[j]i;// 找出所有关键数存到 b[1] ~ b[j]}}for(inti1;ij;i){printf(%d,b[i]);if(ij)printf( );}return0;} 常见错误提醒错误类型具体表现输入未标记忘记a[t] 1无法识别原始输入顺序错误正确顺序应为从大到小枚举100 → 1输出格式错误忽略最后一个数字后不能有空格数组越界f[t]或a[t]空间开太小导致崩溃✅ 总结归纳本题是集合判定与路径覆盖思想的结合实践建议作为 1001 题的进阶练习来理解。熟练掌握 卡拉兹猜想 模拟建模学会在路径遍历中构建覆盖集合筛选出未被覆盖的“关键节点”注重输出格式控制避免低级失误。 思维拓展本题的核心是构造一套“路径逆向验证系统”关键数必须“独立存在不被其他路径覆盖”。本质是集合操作输入集合A路径覆盖集合F输出集合 A - F设计f[]与a[]两套标记数组分别记录路径与输入集合是处理集合差集的一种经典思路。