PAT乙级真题1005继续(3n+1)猜想

版权声明:转载请附上链接,虽然我都不信有人转。 https://blog.csdn.net/gezhishigechuan_/article/details/82147910

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

   由于笔者能力有限,在做这个题的时候走了不少弯路。其实这个题也并不算很难。如果只要求通过,甚至是非常简单的,但是如果要考虑空间的占用率和运行效率的话就必须想的稍多一些。我也看过其他博主写的这个题的答案,其中不少都是虽然简短但是会极大浪费空间的程序。这种做法在数据尚少的情况下倒无所谓,但是数据一旦多了起来那造成的资源浪费就不忍直视了。笔者不才,如有高手莅临,愿闻其教。

分析:

1.输入相应的数据,因为要找出具有一定特征的数并输出,所以用is_key_num与数据共同组成结构体,且初始化          is_key_num的值为1。

2.callatz猜想的思想已给,封装成函数。

3.每个输入数都要计算callatz猜想数,由其定义可知每个输入值得产生的猜想数个数不一定相同,猜想数的存储结构用链表以方便增减数据。

4.每计算一个输入值的callatz猜想值后,用所有猜想值依次与其他所有is_key_num==1的输入元素对比。最终即确定出关键数。

/*总分:25,得分:25*/
#include<stdio.h>
#include<stdlib.h>
#define YES 1
#define NO 0
typedef struct{		//num为输入的数据,is_key_num为关键数的标志位 
	int num;
	int is_key_num;
}data;
typedef struct nd{	//用于存放每个输入数据的Cllatz猜想数,构成链表 
	int num;
	struct nd* next;
}cal_sq_node;
cal_sq_node* callatz(int x); //x:要计算callatz猜想数的值,返回头结点 
int main(){
	int n;
	scanf("%d",&n);	//输入数据的个数 
	if(n<1||n>100)
		return(1);
	data input_num[n];	//数据将用data形式存储在数组中  
	for(int i=0;i<n;i++){ 
		scanf("%d",&input_num[i].num);
		input_num[i].is_key_num=1; 	//设定每个输入的数据均为关键数
	} 
//	printf("%d\n",input_num[2].num);//debug:数据输入正确 
/*	//debug:测试callatz() 
	cal_sq_node* sq_head=callatz(input_num[0].num);
	cal_sq_node* sq_ptr;
	for(sq_ptr=sq_head->next;sq_ptr->next!=NULL;sq_ptr=sq_ptr->next){
		printf("sq_ptr_add:%p,sq_ptr_num:%d\n",sq_ptr,sq_ptr->num);
	} 
*/	
	int num_of_flag_YES=n;	//num_of_falg_YES用于表示关键数的个数 
	int j=0;	
	for(int k=0;k<n;k++){//计算input_num[].is_key_num为YES的猜想值 
		if(input_num[k].is_key_num==NO)	//此数的猜想值链表必定已经被前面的链表所包含,不必再次计算 
			continue;
		cal_sq_node* cal_sq_head=NULL;
		cal_sq_node* cal_sq_ptr=NULL;
		cal_sq_head=callatz(input_num[k].num);//得到calltz数的链表头指针 		
		cal_sq_ptr=cal_sq_head;
		while(cal_sq_ptr->next!=NULL){
			j=0;	
		//	printf("%d\n",cal_sq_ptr->num);
			while(j<n){	//若input_num[j].is_key_num==NO则跳过,不用再次比较次数,继续判断下个数 
				if(input_num[j].is_key_num==YES&&cal_sq_ptr->num==input_num[j].num){
					input_num[j].is_key_num=NO;
					num_of_flag_YES--;
				}
				j++;
			} 
			cal_sq_ptr=cal_sq_ptr->next;
		}
		//用callatz猜想值与其他输入值比较后,将所有此输入值的所有callatz值占用的空间清空
		cal_sq_ptr=cal_sq_head;
		cal_sq_node* cal_sq_temp;
		while(cal_sq_ptr->next!=NULL){
			cal_sq_temp=cal_sq_ptr;
			cal_sq_ptr=cal_sq_ptr->next;
			free(cal_sq_temp);
		} 
		free(cal_sq_ptr);
	} 
//	printf("number of num_of_flag_YES:%d\n",num_of_flag_YES);//debug 
	int key_num_arr[num_of_flag_YES];
	for(int m=0,c=0;m<n;m++){	//将确定为关键数的输入值一起放在数组key_num_arr[]中 
		if(input_num[m].is_key_num==YES){
			key_num_arr[c]=input_num[m].num;
	//		printf("key_num_arr[%d]:%d\n",c,key_num_arr[c]);
			c++;
		}
	}
	//此时的key_num_arr是无序的,排序方案:每个元素均与其后的所有元素对比 
	for(int k=0;k<num_of_flag_YES;k++){ //对key_num_arr[]从大到小排序并打印 
		int max_=key_num_arr[k];
		int temp;
		for(int j=k+1;j<num_of_flag_YES;j++){
			if(max_<key_num_arr[j]){
				temp=max_;
				max_=key_num_arr[j];
				key_num_arr[j]=temp;
			}
		}
		if(k!=0)
			printf(" %d",max_);
		else
			printf("%d",max_);
	} 
	
}
cal_sq_node* callatz(int x){
	cal_sq_node *head_node,*ptr_node;
	head_node=(cal_sq_node*)malloc(sizeof(cal_sq_node));
//	first_node=(cal_sq_node*)malloc(sizeof(node));
	if(!head_node)
		exit(1); 
	head_node->next=NULL;
	ptr_node=head_node;
	while(x!=1){ //计算猜想值并存放至链表 
		if(x%2==1)
			x=(3*x+1)>>1;
		else
			x=x>>1;
		ptr_node->next=(cal_sq_node*)malloc(sizeof(cal_sq_node));
		ptr_node=ptr_node->next;
		ptr_node->num=x;
		if(x==1)
			ptr_node->next=NULL;
	}
	
/*	//debug:检查callatz数组成的链表是否准确	
	for(ptr_node=head_node->next;ptr_node->next!=NULL;ptr_node=ptr_node->next){
		printf("ptr_node add:%p,ptr_node num:%d\n",ptr_node,ptr_node->num);
	} 
*/
	return head_node;
}

猜你喜欢

转载自blog.csdn.net/gezhishigechuan_/article/details/82147910