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

题目

卡拉兹(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 个空格隔开,但一行中最后一个数字后没有空格。

注意,关键数不是能覆盖数列内所有数字的数字,而是不能被数列中的其他数字所覆盖的数字。

解题

我自己写了一串代码,大概有50行,开始时有两个测试点一直过不了,也找不到原因。排查之后发现是冒泡排序法有问题,终于也算过了。我也看了大佬写的代码,读起来神清气爽,妙啊。也不知道我再练多少日子才能练出那样的功力。

我的代码

#include<iostream>
#include<cstring>
int a[105],b[105],c[15];
using namespace std;
int main(){
	int n,i,j,s,t,r;
	cin>>n;
		s=0;t=0;r=0;
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		for(i=0;i<n;i++){
			cin>>a[i];			
		}
		for(i=0;i<n;i++){
			s=a[i];
			while(s!=1){
				for(j=0;j<n;j++){
					if(a[j]==s) b[j]++;//每被覆盖一次记一次数(该数本身也算在内) 
				}				
				if(s%2==0) {s/=2;} 
				else {s=(3*s+1)/2;} 			
			}
		}
	for(i=0;i<n;i++){
			if(b[i]==1)
			c[t++]=a[i];
		}
		for (i = 0; i < t; i++){
        int key=0;
        for (j = 0; j+1<t-i; j++){
            if (c[j] > c[j+1]){
                key=1;
                r=c[j];c[j]=c[j+1];c[j+1]=r;
            }
        }
        //如果 key 值为 0,表明表中记录排序完成
        if (key==0) {
            break;
        }
        }
	for(i=t-1;i>=0;i--){
		cout<<c[i];
		cout<<(i==0?"\n":" ");
	}
	return 0;
}

大佬的代码来自铁肥宅

#include <stdio.h>
#include <stdlib.h>
int count[101];
void Callatz(int);
int cmp(const void *,const void *);
int main()
{
    int i,K;
    scanf("%d",&K);
    int N[K],ans[K],n;
    for(i=0 ; i<K ; i++)
    {
        scanf("%d",&N[i]);
        Callatz(N[i]);
    }
    for(i=0,n=0 ; i<K ; i++)
        if(count[N[i]] == 0)
            ans[n++]=N[i];
    qsort(ans,n,sizeof(int),cmp);
    for(i=0 ; i<n ; i++)
        printf("%s%d",i == 0 ? "" : " ",ans[i]);
}
void Callatz(int n)
{
    while(n != 1)
    {
        n = n % 2 == 0 ? n / 2 : (3*n+1)/2;
        if(n<=100)
            count[n]++;
    }
}
int cmp(const void *a,const void *b)
{
    return *(int *)b-*(int *)a;
}


compar参数
compar参数指向一个比较两个元素的函数。比较函数的原型应该像下面这样。注意两个形参必须是const void *型,同时在调用compar 函数(compar实质为函数指针,这里称它所指向的函数也为compar)时,传入的实参也必须转换成const void *型。在compar函数内部会将const void *型转换成实际类型。
int compar(const void *p1, const void *p2);

如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的前面;
如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;
如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的后面。
  
另附上qsort()函数的使用方法(转)

C++ qsort在"iostream" c在头文件stdlib.h中,strcmp在string.h中。下列例子默认从小到大排序即(a>b返回>0),反之从小到大排序

1、对int类型数组排序
int num[100];
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}
qsort(num,100,sizeof(num[0]),cmp);

2、对char类型数组排序(同int类型)
char strs[100];
int cmp( const void *a , const void *b )
{
return *(char *)a - *(int *)b;
}
qsort(strs,100,sizeof(strs[0]),cmp);

3、对double类型数组排序(特别要注意)
double dbs[100];
int cmp( const void *a , const void *b )
{
return *(double *)a > *(double *)b ? 1 : -1;
}
qsort(dbs,100,sizeof(dbs[0]),cmp);

4、对结构体一级排序
struct d
{
int a;
}arr[100]
int cmp( const void *a ,const void b)
{
  return (
(d )a)->a > ((d *)b)->b ? 1 : -1;
}
qsort(arr,100,sizeof(arr[0]),cmp);

5、对结构体二级排序
struct d
{
int x;
int y;
}arr[100];
//按照x从小到大排序,当x相等时按照y从大到小排序
int cmp( const void *a , const void *b )
{
struct d *c = (d *)a;
struct d *e = (d *)b;
return c->x != e->x?c->x - e->x:return e->y - c->y;
}
qsort(d,100,sizeof(d[0]),cmp);

6、对字符串进行排序
struct dict{
char str[100];
}dicts[100]
int cmp ( const void *a , const void b )
{
  return strcmp( (
(dict )a)->str , ((dict *)b)->str );
}
qsort(dicts,100,sizeof(dicts[0]),cmp);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值