PAT(Basic Level)总结(1001~1019)

前言

最近开始刷PAT乙级的题目,乙级题目共有95道,我计划写5篇博客来总结刷题的过程。这是第1篇博客来记录1001~1019题的心得体会。


文章目录

  • 前言
  • 解题关键词
  • 1001
  • 1002
  • 1003
  • 1004
  • 1005
  • 1006
  • 1007
  • 1008
  • 1009
  • 1010
  • 1011
  • 1012
  • 1013
  • 1014
  • 1015
  • 1016
  • 1017
  • 1018
  • 1019
  • 总结


解题关键词

分类讨论、STL的简单使用(C with STL)


STL

1001

害死人不偿命的(3n+1)猜想(15 分)

总结:分奇偶讨论、自增计数(count++)

1002

写出这个数(20 分)

1.大数处理
由于C++没有类似于Java的BigInteger,通过将大数(超过long long范围的数)按位存储在数组中。
2.字符数字转化为相应整数
根据ASCII码:字符-0x30即可得到相应数字。
3.输出格式要求
“拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格”:在每一个拼音的前面加空格,通过设置标志位来控制第一个拼音前没有空格。

1003

我要通过! (20 分)

总结:理解题意是关键,题目关注的是A的数量规律。根据第三条要求可以得出递推公式:a*(b+1)= c+a。

1004

成绩排名 (20 分)

总结:声明一个结构体存储学生的信息,调用sort排序即可。

1005

继续(3n+1)猜想 (25 分)

总结:
按照1001的方法遍历每一个输入的数,记录运算过程中出现的数,即可发现“没有被覆盖的数”。由于无法事先确定有多少个关键数,因此可声明一个vector存储“关键数”(没有被覆盖的数),调用push_back存储和sort排序。

1006

换个格式输出整数 (15 分)

总结:将整数用取模的方法得到各个数位。

1007

素数对猜想 (20 分)

总结:首先使用埃拉托色尼筛选法获取10万以内的素数表(《算法笔记》5.4.2有详细介绍)。之后再依次遍历相邻的两个素数。

1008

数组元素循环右移问题 (20 分)

题干提到:如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
答:采用一种翻转的方法,如下图函数所示。设数组总长度为N,需右移的长度为M。先对数组的前N-M项进行翻转;再对后M项进行翻转;最后对整个数组(N项)进行翻转,即可得到右移后的数组。

void exchange_begin_end(int arr[], int begin_idx, int end_idx)
{
     
	int mid = (begin_idx+end_idx)/2;
	int i;
	for(i=begin_idx; i<=mid; i++)
	{
     
		int temp = arr[i];
		arr[i] = arr[begin_idx+end_idx-i];
		arr[begin_idx+end_idx-i] = temp;	
	}
}

1009

说反话 (20 分)

总结:vector的使用(push_back函数调用)。
思路:循环遍历整个字符串,如果读取到字符将其暂存到一个string类型的tmp中;如果遇到一个空格字符,则把此时的tmp添加到vector中,并把tmp清空。

1010

一元多项式求导 (25 分)

总结:注意题目的“零多项式”是系数指数都为0,才输出0 0。若输入的是5 0或0 4,则什么也不输出。

1011

A+B 和 C (15 分)

总结:由于区间范围最大是2的31次方,因此不能使用int类型声明A、B、C,可使用long类型,对应scanf要用%ld长整型。

1012

数字分类 (20 分)

总结:分5类讨论,5个if简单粗暴;设置5个标志表明是否有此类元素的产生;输出时判断是否有某类元素产生,有则输出,无则输出N。

1013

数素数 (20 分)

总结:同样采用1007中的埃拉托色尼筛选法,与1007区别在于要获得第10000个素数,而不是获得10000以内的素数,1013的计算量更大,需要设置更大的表长,经测试第10000个素数是104729,因此设置步长大于104729即可。

1014

福尔摩斯的约会 (20 分)

总结:在输入的字符串中按规律找出三个信息:星期、小时、分钟。星期和小时是在字符串1和字符串2中寻找,设置day_flag先找星期再找小时。字符串3和字符串4中找第一个相同的字母,分大小写。

1015

德才论 (25 分)

总结:
1.分5类讨论(5个等级),声明一个结构体存储考生的信息(ID、德分、才分以及等级)。注意要将题干中其他达到最低线的考生都归于第4类,第5类是未达到最低线的。
2.分级排序(自定义sort函数的排序规则)

bool cmp_sum(Student x,Student y)
{
     	
	if(x.level != y.level)
		return x.level < y.level;
	else		//x.level == y.level
	{
     
		if(x.moral+x.intelligence != y.moral+y.intelligence)
			return x.moral+x.intelligence > y.moral+y.intelligence;
		else    //总分相同
		{
     
			if(x.moral != y.moral)
				return x.moral > y.moral;
			else
				return x.name < y.name;
		}	
	}
}

1016

部分A+B (15 分)

总结:字符串输入A和B,字符输入DA和DB,方便之后的比较。

1017

A除以B (20 分)

总结:大数除法。
1.声明一个大数的结构体:num存储数字,len表示该数的长度。

struct big_num
{
     
	int num[1001];
	int len;
	big_num() 	//Init big_num
	{
     						
		memset(num,0,sizeof(num));
		len = 0;
	}	
}; 

2.字符串输入存入big_num中的int类型数组

big_num change(char str[])
{
     
	big_num a;
	a.len = strlen(str);
	int i;
	for(i=0; i<a.len; i++)
	{
     	//整数高位存储在数组的高位
		a.num[i] = str[a.len-1-i] - '0';
	}
	return a;
}

3.大数除法

big_num divide(big_num a, int b, int &r)	//a是除数,b是被除数,r是余数
{
     	
	big_num c;					//商
	c.len = a.len;
	int i;
	for(i=a.len-1; i>=0; i--)	//从高位开始进行除法 
	{
     
		r = r*10 + a.num[i];
		if(r<b)					//不够除, 商为0
			c.num[i] = 0;
		else					//够除,求商求余
		{
     
			c.num[i] = r/b;
			r = r % b;					
		} 
	}
	while(c.len-1>=1 && c.num[c.len-1]==0)
	{
     	//去除高位的0
		c.len--;
	}
	return c;
}

1018

锤子剪刀布 (20 分)

总结:通过遍历并比较输入,分别统计双方胜平负的次数,较为简单;另外需加上两个计数器记录双方获胜时的手势,如下面的代码所示。

int A_Count[3] = {
     0};	//0->B 1->C 2->J
int B_Count[3] = {
     0};	
int get_max_index(int arr[])
{
     
	int max = -1, index = 0;
	for(int i=0; i<3; i++)  //按照BCJ的顺序进行遍历
	{
     
		if(arr[i]>max)      //大于max才会变更arr的索引
		{
     
			max = arr[i];
			index = i;
		}
	}
	return index;
}
//处理后... 输出获胜最多的手势
    char arr[3] = {
     'B', 'C', 'J'};
    printf("%c %c", arr[get_max_index(A_Count)], arr[get_max_index(B_Count)]);

1019

数字黑洞 (20 分)

总结:对一个整数的各个位进行排序,需先把其转化为一个字符串;之后要对这个字符串进行减法运算,需再把其转化为整数。要注意:4位都相同的整数。

//4位整数与字符串之间的互化
int arr_to_int(int arr[])
{
     
	int a;
	a = arr[0]*1000 + arr[1]*100 + arr[2]*10 + arr[3];
	return a;
}
void int_to_arr(int a)
{
     
	int m = 1;
    for(int i=0; i<4; i++)
    {
     
        arr[3-i] = (a/m)%10;
        m *= 10;
    }
}

总结

感想:目前到1019题为止,还没有涉及到数据结构的知识,虽然PAT basic level题库只是做做算术题和处理字符串,但其实并不是很简单。要想获得大部分分数,首先要将题意转化为合适的条件用代码来描述,并针对要解决的问题做出一个总体的逻辑框架,再此基础上若想通过所有测试点还对逻辑的严密性要求较高。通过刷PAT题确实提高了我的编码能力。

你可能感兴趣的:(PAT,算法,c++,字符串)