今天的这道题目着实把我难住了好久,不愧是PAT乙级中值25分的一道题。

这道题呢,是在PAT乙级1001的基础上来增加了一些难度,但是呢,还没有涉及到数据结构,可以说只需要盘清楚逻辑,就可以做这道题了。

我们先来看一看这道题描述了什么:

当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推到的每一个数。

例如对n=3验证的时候,我们需要计算3、5、8、4、2、1,当我们对n=5、8、4、2进行验证的时候,由于我们之前在验证3的时候已经递推过了,所以就不需要验证这些数字。

看到这句话的时候,我还有些不解,但其实很好理解。

我来稍微理一理逻辑:

当n=3的时候,n=3是奇数,根据卡拉兹猜想,奇数要3n+1,然后除以2,很显然可以得到5;

继续往下推,n=5是奇数,(3n+1)/2=8;

偶数是直接除以2,所以8/2=4,4/2=2,2/2=1。

很显然,后面的这些数字5、8、4、2,在我们用卡拉兹猜想验证n=3的时候已经都用到过了,自然而然地也不需要再进行验证了。

审题分析,理清逻辑,流程图

我在每次做这些题目的时候,都会先理逻辑,然后画一个流程图,主要目的呢就是为了帮助我之后如果想来复盘题目的话,能够快速地知道自己哪里出现了问题,并且会较为详细地记录自己的做题过程。

1、第一行给出一个正整数K。

2、第二行给出K个互不相同的待验证的正整数n(1<n<=100)的值,由于要对这些给出的正整数进行数值上的判断,所以最好用数组来进行存储,主要是用来存储一系列相同类型的变量,然后再对数组中的数据来进行处理,需要在for循环中。

3、接下来就是要进行卡拉兹猜想验证,与之前状态相同,就是遍历整个数组,然后从第一个数字开始验证,所以我们要用一个for循环来遍历整个数组。

4、然后,很多数字会在进行卡拉兹猜想验证的时候出现,只要把这些出现的数字与原本数组中的数字进行比较,亦或者直接把原本数组中的这些数字给删除/给这些出现过的数字标上相同的记号,然后再下一次遍历的时候,把这些标过记号的数字不进行输出即可,但是,注意,不能在该数组中进行操作,因为会让该数组的值发生一定的变化,所以需要一个一模一样的数组。

5、数字间用空格隔开,且最后一个数字后面没有空格,先循环输出n-1项,再单独输出最后的第n项。

用一个流程图就能较为直观地看出这道题目的逻辑,接下来就是代码的实现。

代码的实现

这道题呢,对于代码的实现来说,难度可能会有点存在,当然也不像PAT1004一样需要用到一个结构体,正如我之前对这道题目分析的那样,只需要用到数组就行了,一个数组不行那自然可以用两个数组,两个数组不行可以用三个数组,这道题目并没有要求要用到数据结构,所以说,写的稍微复杂些也没什么关系,当然了,代码越简洁越好。

首先,是进行全局变量的定义。

正如我之前对这道题目的逻辑分析讲的那样,我需要一个数组来存储我输入的所有正整数,同时,我也需要一个数组来复制这些正整数,在进行卡拉兹猜想递推的时候,要把这些标记给去除出来,满足这些标记的,就不要显示了(因为已经进行验证过了)。

而不满足这些标记的,才是我们最终需要的。

#include <stdio.h>
int main() {int k = 0;//第一行给出的正整数int number[100]; //用来存储输入的这些数int replace[100] = {1}; //用来做标记的数组,假设我们对该数组中的每一个位置做标记为0,那么只要把特定位置的给取出来就行了int count = 0;scanf("%d",&k);//输入正整数kfor(int i=0; i<k; i++){scanf("%d", &number[i]);//输入k个正整数,并用数组的形式来进行存储replace[number[i]] = 1;}//目的是把那些重复的数给剔除,注意,这里的number[i]已经发生了变化,所以不能再用number[i]来作为最终的结果//以下做法满足卡拉兹猜想for(int i=0; i<k; i++){if(number[i]%2==0){number[i] = number[i]/2; //偶数时直接除以2//那么在该位置做上标记,也就是说此位置的replace[i] = 2;replace[number[i]] = 2;}else if(number[i]%2==1){number[i] = (3*number[i]+1)/2; //奇数时为(3n+1)/2replace[number[i]] = 3;}}for(int i=100; i > 0; i--){  //因为我们在平时输出的时候,都是正向输出,所以我们这里只需要反向输出即可if(replace[i] == 1){if(count>0){printf(" ");}printf("%d", i);count++;}}
}

该代码在Xcode上面能够完整运行并给出相应的结果:

但是呢,这样却产生了一些问题:我在PAT网站上跑的时候只有15分,却没有拿到剩下的10分,这着实奇怪,对于代码逻辑没有问题,但是最终结果产生了一些问题,那可得抽丝剥茧来进行反思了。

经过我的观察,是发现没有满足这道题的一些特定条件:

1、K要小于100

2、n的范围要大于0小于等于100

顺着这个想法我试着加上了一些条件判断。

但是最终做出来的结果反而没有答案正确了,只剩下部分正确,这就更奇怪了。

        else if(number[i]%2==1){number[i] = (3*number[i]+1)/2; //奇数时为(3n+1)/2replace[number[i]] = 3;}

继续进行排查

我发现,这里涉及到一个数组越界的问题了。

由于我定义的初始数组replace[100]范围太小了,是从0开始到99。

而我后面的条件语句判断是100,所以这里就产生问题了。

于是我把replace[i]给调整到replace[1000]了,诶,就发现没什么问题了。

当然,我这里没有对K数值的大小进行判断,不过呢问题也不大,如果要对K数值的大小进行判断的话,只需要在第一个for循环之前加一个if(K<100)的条件语句即可。

#include <stdio.h>
int main() {int k = 0;//第一行给出的正整数(<100)int number[1000]; //用来存储输入的这些数, 0< n = number <=100int replace[1000] = {1}; //用来做标记的数组,假设我们对该数组中的每一个位置做标记为0,那么只要把特定位置的给取出来就行了int count = 0;scanf("%d",&k);//输入正整数kfor(int i=0; i<k; i++){scanf("%d", &number[i]);//输入k个正整数,并用数组的形式来进行存储if(number[i]>1&&number[i]<=100){replace[number[i]] = 1;}}//目的是把那些重复的数给剔除,注意,这里的number[i]已经发生了变化,所以不能再用number[i]来作为最终的结果//以下做法满足卡拉兹猜想for(int i=0; i<k; i++){while(number[i]!=1){if(number[i]%2==0){number[i] = number[i]/2; //偶数时直接除以2//那么在该位置做上标记,也就是说此位置的replace[i] = 2;if(number[i]<=100){replace[number[i]] = 2; //给这些已经递推过的数标上2}}else if(number[i]%2==1){number[i] = (3*number[i]+1)/2; //奇数时为(3n+1)/2if(number[i]<=100){replace[number[i]] = 3; //给这些已经递推过的数标上3}}}}for(int i=100; i > 0; i--){  //因为我们在平时输出的时候,都是正向输出,所以我们这里只需要反向输出即可if(replace[i] == 1){if(count>0){printf(" ");}printf("%d", i);count++;}}
}

最后的测试结果:

总结

这道题目难度的确有一点,我自己做了好长时间,而且也查阅了资料才做出来的,总的来说主要是因为我对C语言的确不是很熟悉,所以得好好反思,再继续努力才行!!!

PAT乙级1005,用C语言进行编程,继续卡拉兹猜想相关推荐

  1. PAT(乙级) 1001 害死人不偿命的(3n+1)猜想 (15 分) (python3)

    PAT(乙级) 1001 害死人不偿命的(3n+1)猜想 (15 分) (python3) 第一次写点博客记录自己学习算法的过程,因为个人能力有限,会不定期发布一些PAT上题目的代码 PAT 乙级的1 ...

  2. 2021年秋季PAT乙级题解(C语言)

    7-1 好数 (15 分) 好数是指由一对正整数 a<b 按照 a^2+ab+b ^2这个规则生成的数,a 和 b 就称为这个好数的源头.例如 91 就是一个好数,因为 5 ^2+5×6+6 ^ ...

  3. pat 乙级 1005 继续(3n+1)猜想(C++)

    题目 卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数.例如对 n=3 进行验 ...

  4. PAT乙级 1005 继续(3n+1)猜想 (25分)

    1005 继续(3n+1)猜想 (25分) 卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中 ...

  5. PAT 乙级 ------ 1046~1050 划拳、编程团体赛、数字加密、数列的片段和、螺旋矩阵附思路和代码

      这个鬼天气欸,又降温到十几度了.看帖子的你,今天也要开心啊!!!PEACE & LOVE 1046 划拳 思路: 每次读取四个数,根据规则求和比较,只有一方胜利一方失败从才会喝酒,同赢同输 ...

  6. 【PAT乙级】1059 C语言竞赛 (20 分)

    题目地址 #include<bits/stdc++.h> using namespace std; int n,k; string s[5]={"","Mys ...

  7. 【PAT乙级】1036 跟奥巴马一起编程 (15 分)

    题目地址 #include<cstdio> #include<iostream> #include<string> using namespace std; int ...

  8. PAT乙级 1005继续3n+1猜想

    当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数.例如对 n=3 进行验证的时候,我们需要计算 3.5.8.4.2.1,则当我们对 n=5.8.4.2 进行验证的时候, ...

  9. PAT乙级(1005 继续(3n+1)猜想)

    卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数.例如对 n=3 进行验证的时 ...

最新文章

  1. 专访 | 融资4.1亿美元,估值15亿美元,这家AI初创公司凭什么“这么贵”?
  2. Beep()之我迷糊了……
  3. 实验研究信标无线电能输出功率的因素
  4. 第十五届全国大学智能汽车提问回答问题 2020-8-9
  5. 远程备份SQL Server 2005数据库
  6. python selenium post_python爬虫 selenium标记信息修改
  7. 全局描述符表(GDT)——《x86汇编语言:从实模式到保护模式》读书笔记09
  8. 完全优化MySQL数据库性能的八大巧方法
  9. 习题6-2 使用函数求特殊a串数列和 (20 分)
  10. XP设置文件夹默认打开方式改为“资源管理器”
  11. 关于std::string和 C-style string的一些知识点备忘
  12. php zitian虚拟主机配置_虚拟主机的发展
  13. MacOS 安装 Matlab R2021b 手记
  14. 节后 威金/Viking 来拜年
  15. html问号字符串,问号html
  16. 后门准则(Backdoor Criterion)与前门准则(Frontdoor Criterion)
  17. 【编译系统】什么是PL/0和类Pcode虚拟机
  18. 探索浏览器(二)向DNS服务器查询Web服务器的IP地址
  19. 在Windows 使用Administrator账户
  20. word 调整word中一部分格式,全文都跟着变的解决办法

热门文章

  1. 1.1小程序内置tabbar和自定义tabbar区别
  2. MIT 6.828 lab1 part2
  3. 计算机系统基础栈帧,2020春-计算机系统基础(一)-中国大学mooc-题库零氪
  4. 多智能体协同传输的事件触发通信与控制的深度强化学习(ICRA-2021)
  5. 【深度学习】语义分割-综述(卷积)
  6. 微信小程序实现一个简单的加减法的计算器
  7. NSL-KDD数据集介绍以及字段介绍
  8. 记Android新版本构建导致的问题-android 不能直接引用module资源
  9. 如何判断点是否在凸多边形内部(用于碰撞检测)
  10. 【Test】GacUI 1.0 眼看着就要写完了 (4)