近日参加了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,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就是用来判定是否超出。