记2021PAT秋季题解

近日参加了2021年9月11日的PAT秋季乙级比赛,记录一下自己做出来和没做出来的题= =

第一次写题解,是为了方便自己以后查看,如有不对请大佬们指出。

7-1好数

代码如下:

#include<bits/stdc++.h>
using namespace std;
int haoshu[10001];
int aa[10001];
int bb[10001];
bool judge(int c) {
	int a, b;
	for (int a = 1; a < sqrt(c); a++) {
		for (int b = a + 1; b < sqrt(c); b++) {
			if ((a * a + a * b + b * b) == c) {
				return true;
				return 0;
			}
		}
	}
	return false;
}
int main() {
	int bigger, n, a, b, c, count = 0;//c为好数。bigger是比该数大的最小好数。 
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> c;
		if (judge(c)) {
			cout << "Yes" << endl;
			for (int a = 1; a < sqrt(c); a++) {
				for (int b = a + 1; b < sqrt(c); b++) {
					if ((a * a + a * b + b * b) == c) cout << a << " " << b << endl;
				}
			}
		} 
		else if (judge(c) == false) {
			for (int j = c + 1;; j++) {
				if (judge(j)) {
					bigger = j;
					break;
				}
			}
			  cout << "No" << " " << bigger << endl;
			for (int a = 1; a < sqrt(bigger); a++) {
				for (int b = a + 1; b < sqrt(bigger); b++) {
					if ((a * a + a * b + b * b) == bigger) cout << a << " " << b << endl;
				}
			}
		}
	}
}

这题我一开始的代码试图把判断是否为好数和输出源头一起写,然后发现这样会导致每找到一个源头就输出一句"Yes",于是我就单独写了一个判断语句judge来判断这个数是否为好数。

当judge为真时,输出yes然后利用一个嵌套for循环语句来输出a,b。仔细观察题目发现a<b,因此b的初始值都是a+1,从a的后面一项开始查找。根据公式a^2+ab+b^2得知a,b小于sqrt(c)。然后输出就好了。

当judge为假时,我的思路是先找到那个比该数大的最小好数。从c+1也就是c的后一位开始找,再利用judge语句找到好数,然后break掉。 然后就是和上面一样的步骤。

7-2 物以类聚

这道题其实思路还算清晰,但是因为本人水平太菜,在写代码的时候因为自己设的数组有点模糊不清,把自己搞晕了= =   花了很长时间才把最后一句代码写对。

还是先送上我的代码:

#include<bits/stdc++.h>
using namespace std;
const int f=1e7+10;
bool s[f];
int ss[f];
int sss[f];
int b[f];
//用来算各位的乘积 
int chengji(int x){  
	int sum=1;
	while(x!=0){
		int c=x%10;
		sum=sum*c;
		x=x/10;
	}
	return sum;
}
//这个函数下面没有用到  是我一开始思路顺手写的
bool judge(int a,int b){   
	if(chengji(a)==chengji(b)) return true;
	else return false;
}
int main(){
	int n,count=0,max=0,min=100000000;
	cin>>n;
	//读入样例 
	for(int i=0;i<n;i++){  
		cin>>ss[i];
	}
	//sss数组用来存每个乘积出现的次数 
	for(int i=0;i<n;i++){   
		sss[chengji(ss[i])]++;
		} 
	//s数组用来判断该乘积是否重复出现,同时用count来求归类的数量
	//max用来储存最大的类的值!不是具体哪一个最大类 
	for(int i=0;i<n;i++){
	     if(s[chengji(ss[i])]==false) {
		 	s[chengji(ss[i])]=true;
		 	count++;
		 	if(sss[chengji(ss[i])]>=max){
		 			max=sss[chengji(ss[i])];
            }
            
		 }
	}
	//如果是最大类,并且这个类里乘积比最小值小,就替换最小值 
		 for(int i=0;i<n;i++){
		 	if(sss[chengji(ss[i])]==max){
			 	if(chengji(ss[i])<min)
			 	min=chengji(ss[i]);
			 }
		 }	
	//输出 
		cout<<count<<" "<<min<<endl;
	}

思路就是:先用代码求出每个输入的各位乘积,然后把乘积的值当做地址存入一个bool数组,默认bool数组为false,每存入一个就把他改成true,然后count++,这样就可以找到归类的数量。

然后再用max来储存最大类的值,不是数量,因为像样例的话最大类就有三个,我们需要在下面的代码判断当前数组是不是最大类,然后再来找最大类的最小乘积。

在下面的代码中,如果当前类是最大类,那么用if语句来判断该乘积是否比最小值还小,如果是就替换掉最小值。

最后输出!  圆满结束,考试的时候真的纠结死我了  最后换最小值那步。

7-4 数组和链表

这道题我是考完之后才做出来的(不知道对没对没测试过,但是样例对了)。太菜了纯新手。希望大佬指出错误。

思路还是挺清晰的,我感觉比7-3简单一点呢

先附上代码:

#include<bits/stdc++.h>
using namespace std;
int a[10000100];
int b[1010];
int c[10001000];
int main(){
	int n,k,count=0,sum,s=0,sumb=0,max=0;
	cin>>n>>k;
	//读入  sumb是下面代码会用到的 
	for(int i=0;i<n;i++){
		cin>>a[i]>>b[i];
		sumb=sumb+b[i];
	}
//a是初始地址,b是长度,c是用户访问的数组下标 
	for(int i=0;i<k;i++){
		 cin>>c[i];
		 	count=0;
		 	sum=0;
		 	s=0;
		 for(int j=0;j<n;j++){ 
		 	if(count>c[i]){
			 	 sum=a[j-1]+(c[i]-(count-b[j-1]))*4;
			 	 cout<<sum<<endl;
			 	 break;
			 }
		 	else {
		 		count=count+b[j];
		 		s++;
			 }
		 }	
		 if(s>max&&count<sumb) max=s;
		 if(count>=sumb) cout<<"Illegal Access"<<endl;
	} 
	cout<<max<<endl;
}

如果count比c[i]小就加上b[j],因为比c[i]小说明还没有到对应的数组。

如果count加到最后比所有给定地址长度都大或者相等,则说明超出了。就输出"Illegal Access"。

根据题目给的样例说明可以很轻松的推出计算地址的关系:sum=a[j-1]+(c[i]-(count-b[j-1]))*4

就拿第二个输入的访问地址12来说:

b[0]+b[1]=11<12,所以还得再加,11+b[2]=21>12.所以开始的地址应该就是a[2],用a[2]这个初始地址加上(12-(21-10))*4就是最终的地址。

s++则是为了找到一共创建了几个数组。每一次count+b[j]都说明需要新开一个数组,那我们只要一直++就好了,然后把最大的输出。但是,因为当s比总数组数都大时,就说明Illegal Access了,那这个s的值肯定就不可取,所以使用if(s>max&&count<sumb)   这个count<sumb就是用来判定是否超出。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值