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

来源:互联网 发布:黑陶茶具含铅高 知乎 编辑:程序博客网 时间:2024/05/16 13:01
1005. 继续(3n + 1)猜想(25)
卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。
当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对n = 3进行验证的时候,我们需要计算3、5、8、4、2、1,则当我们对n = 5、8、4、2进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这4个数已经在验证3的时候遇到过了,我们称5、8、4、2是被3“覆盖”的数。我们称一个数列中的某个数n为“关键数”,如果n不能被数列中的其他数字所覆盖。
现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。
输入格式:每个测试输入包含1个测试用例,第1行给出一个正整数K(<100),第2行给出K个互不相同的待验证的正整数n(1<n <= 100)的值,数字间用空格隔开。
输出格式:每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用1个空格隔开,但一行中最后一个数字后没有空格。
输入样例:
6
3 5 6 7 8 11
输出样例:

7 6

分析:一个数字结构体有两个属性,一。是否在数列中,二是不是关键数。我们刚开始默认0-100这101个数字都不在数列里,但都是关键字。我们每输入一个数据,就把这个数的flag_in置1,表示他是数列里的数,同时记录这个数覆盖过哪些数,把那些数的flag_key置0,别是那些数字被覆盖过了。

当所有的数据都输入完了,我们就可以通过if(n[i].flag_in == 1 && n[i].flag_key == 1)来筛选出关键数。

#include<iostream>using namespace std;struct number{int flag_in=0;//0表示该数字不在样例数列里,1表示该数字在样例数列里int flag_key=1;//0表示该数字不是关键数,1表示该数字是关键数,默认创建的时候都是关键数};int main(){int N, i, temp;number n[20000];//数组开大一点,防止越界cin >> N;for (i = 1; i <= N; i++){cin >> temp;n[temp].flag_in = 1;//输入了该数字,就把该数字的flag_1置1,表示这个数字是样例数列里的while (temp != 1)//开始卡拉兹猜想{if (temp % 2)//如果是奇数temp = (temp * 3 + 1) / 2;else//如果是偶数temp /= 2;n[temp].flag_key = 0;//之后的这个数字被覆盖了,把他的flag_key置0以筛选掉这个数字}}int count = 0;//统计最后有多少个关键数,这样就可以最后不输出空格for (i = 0; i <= 100; i++){if (n[i].flag_in == 1 && n[i].flag_key == 1)//这个数得是样例数列里的数,而且没有被覆盖过count++;}for (i = 100; i >=0; i--){if (n[i].flag_in == 1 && n[i].flag_key == 1){cout << i;count--;//输出一个,剩余的关键数的数量就少一个if (count > 0)//如果是最后一个关键数的话就不输出空格了cout << " ";}}}


原创粉丝点击