2021年春PAT乙级考试 2021.3.13
考试总结
大一狗,前面过了1235题,4题打到了18分一个点死活过不去。最后为了这2分又打了一个多小时,100分。
这次PAT乙级考试,前两题快的话10min左右,第三题也比较熟悉(比pta上的乙级题集要简单)。第四题有坑点,也略有些难度,拿满分不容易。第五题出乎我的意料考了道算法题,本来以为会是数据处理查询一类的,但也因为之前见过这道题却没做对过感到发愁,结果稍微演算一下发现还是可解的。
7-1 打印三角形拼图 (15 分)
一个正方形可以用两个等边直角三角形拼出来。给定正方形的边长、两个三角形和对角线所用的符号,请你打印出这两个三角形拼出的正方形。
输入格式:
输入在一行中给出一个正整数
L
L
L(
2
≤
L
≤
100
2≤L≤100
2≤L≤100,为正方形的边长),同时给出打印上三角形、下三角形、对角线所用的字符。数字和字符间以一个空格分隔。
输出格式:
按输入要求打印这两个三角形拼出的正方形。
输入样例:
6 a b -
输出样例:
-aaaaa
b-aaaa
bb-aaa
bbb-aa
bbbb-a
bbbbb-
解题思路: (这题两分钟真的可以ac)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a;
char b,c,d;
cin>>a>>b>>c>>d;
for(int i=0;i<a;i++)
{
for(int j=0;j<i;j++) cout<<c;
cout<<d;
for(int j=0;j<a-i-1;j++) cout<<b;
cout<<endl;
}
return 0;
}
7-2 赌马 (20 分)
听说香港中文大学有一个教授开发了一个“投注方程式”来赌马,三个赛季就赚了 5000 万港币。现在请你来开发一个简单的赌马程序:假设开赛若干分钟之内都可以下注,而你可以准确获得截止时间最后一刻每匹马到终点的距离和它的瞬时速度,这样你就可以算出每匹马到达终点还需要多少时间。每次下注预测的前三名,中奖的几率是不是很大啊~
输入格式:
输入在第一行中给出一个正整数
3
≤
N
≤
1
0
4
3≤N≤10^{4}
3≤N≤104,是参赛的马匹数量(虽然有点夸张)。随后
N
N
N 行,每行按以下格式给出:
马的编号 到终点的距离 瞬时速度
其中马的编号是 1 1 1 到 1 0 4 10^{4} 104之间的整数,每匹马的编号是唯一无重复的;到终点的距离是 1 1 1 到 1 0 3 10^{3} 103之间的整数,单位为“米”;瞬时速度是 1 1 1到 20 20 20之间的整数,单位为“米/秒”。
输出格式:
在一行中按到达终点的顺序输出预测的前三名马的编号。如果有并列,按编号递增序取前面的输出。
编号间以 1 1 1 个空格分隔,行首尾不得有多余空格。
输入样例:
6
886 500 12
6688 600 18
8866 700 15
2333 500 15
1234 650 11
6666 375 9
输出样例:
2333 6688 886
解题思路: 利用结构体存放每匹马的数据,再用sort函数进行排序,最后输出最快的前三名。
#include<bits/stdc++.h>
using namespace std;
struct ma
{
int num;
double l,speed;
double time;
}a[10005];
bool cmp(const ma& a,const ma& b)
{
if(a.time!=b.time) return a.time<b.time;
else return a.num<b.num;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i].num>>a[i].l>>a[i].speed;
a[i].time=a[i].l/a[i].speed;
}
sort(a,a+n,cmp);
cout<<a[0].num<<" "<<a[1].num<<" "<<a[2].num;
return 0;
}
7-3 拼题 A 是真爱 (20 分)
如果一个人在一段话里很多次提到 pintia,那对拼题 A 就是真爱啦~ 本题就请你检查一下给定的文字中出现了几次 pintia。
输入格式:
输入在一行中给出一个总长度不超过
1
0
4
10^4
104字符的非空字符串,由英文字母和标点符号 , 和 . 以及空格组成,以一个回车结束。
输出格式:
首先在第一行输出给定文字中出现了多少次 pintia 或 Pintia。
如果一次都没有,在第二行输出 wu gan(无感);如果有但不超过 3 次,输出 you ai(有爱);如果超过了 3 次,输出 zhen ai la(真爱啦)。
注意只有当 pintia 作为完整独立的词出现的时候才算一次,即它必须跟其他文字以空格或者标点符号分开。
输入样例 1:
This is a pintiatest.
输出样例 1:
0
wu gan
输入样例 2:
This is apintia test. Hey I love pintia a
输出样例 2:
1
you ai
输入样例 3:
This is apintiatest. Hey I love pintia, really zhen ai pintiala,pintia is my favorite place to go. Come on visit Pintia.
输出样例 3:
4
zhen ai la
解题思路: 遍历。检查每一个独立的单词。
这类问题容易挖的坑是字符串不是以字母或者标点来结尾,而是以一堆空格来结尾。通过加强判断条件可以处理好这个问题。然而本题似乎不需考虑这一点。详见注释。
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a,t="";//t用来存放每个独立的单词
int sum=0;
getline(cin,a);
for(int i=0;i<a.length();i++)
{
while(a[i]!=' '&&a[i]!=','&&a[i]!='.'&&i!=a.length())
//当没有遇到分隔符或者没到数据结尾时,
//将当前的字母加到字符串t后面,用来检查单词
{
t+=a[i];//拼接单词
i++;//i向后移一位
}
//遇到分隔符或到数据结尾时,检查单词
if(t=="pintia"||t=="Pintia") sum++;
t="";//一个独立的单词检查完,一定要清空
}
cout<<sum<<endl;
if(sum==0)cout<<"wu gan";
else if(sum==1||sum==2||sum==3) cout<<"you ai";
else if(sum>3) cout<<"zhen ai la";
return 0;
}
7-4 素数等差数列 (20 分)
2004 年,陶哲轩(Terence Tao)和本·格林(Ben Green)证明了:对于任意大的 n,均存在 n 项全由素数组成的等差数列。例如 { 7,37,67,97,127,157 } 是 n=6 的解。本题就请你对给定的 n 在指定范围内找出一组最大的解。
输入格式:
输入在一行中给出两个正整数:n(≤10)为等差素数数列的项数; MAXP (2≤MAXP<
1
0
5
10^5
105)为数列中最大素数的上界。
输出格式:
如果解存在,则在一行中按递增序输出等差最大的一组解;若解不唯一,则输出首数最大的一组解。若解不存在,则输出不超过 MAXP 的最大素数。同行数字间以一个空格分隔,行首尾不得有多余空格。
输入样例 1:
5 1000
输出样例 1:
23 263 503 743 983
输入样例 2:
10 200
输出样例 2:
199
提交结果:
(已经尽量压时间了,但复盘的时候还是看到几个20ms以内的大佬) |
---|
解题思路: 首先把最大值之前的素数保存到一个数组里,并且将素数做好标记(方便后续判断),之后对数组进行遍历。注意n=1时特判和减少时间复杂度的处理,尤其是判断数列是否成立时的操作。详见注释。
#include<bits/stdc++.h>
using namespace std;
bool jdg(int a)//判断素数
{
if(a==2||a==3) return true;
for(int i=2;i<=sqrt(a)+1;i++)
{
if(a%i==0) return false;
}
return true;
}
bool a[100005];//标记素数
vector<int>st;//存放素数
int n,maxp;
void Init()//初始化素数数组
{
memset(a,false,sizeof(a));
for(int i=2;i<=maxp;i++)
{
if(jdg(i)==true)
{
a[i]=true;
st.push_back(i);
}
}
}
int main()
{
scanf("%d %d",&n,&maxp);
Init();
if(n==1)//n=1一定要写,第3个测试点
{
cout<<st.back();
return 0;
}
//如果没有特判,n=2运行起来的速度将会相当慢。但似乎没有n=2的数据
if(n==2)
{
cout<<2<<" "<<st.back();
return 0;
}
int ans=0,ansc=0;//首项及公差
//以下是对存放素数的vector数组进行遍历
for(int i=0;i<st.size();i++)
{
for(int j=i+1;j<st.size();j++)
{
if(st[i]+(st[j]-st[i])*(n-1)>maxp) break;
/*如果这个等差数列的最后一项大于maxp,break。
其中st[i]为首项,st[j]是第二项,
st[j]-st[i]为公差,*(n-1)为最后一项。*/
int flag=1,cha=st[j]-st[i];
//先假设数列成立,cha为公差。
for(int k=1;k<=n-2;k++)
{
//判断数列每一项是不是都是素数。
if(a[st[j]+k*cha]==false)
{
//如果不是素数,数列不成立,flag=0
flag=0;
break;
}
}
if(flag==1)//数列成立
{
if(cha==ansc)//公差一样取首项大者
{
if(ans<st[i]) ans=st[i];
}
if(cha>ansc)//公差不同选公差大者
{
ans=st[i];
ansc=cha;
}
}
}
}
if(ans!=0)
{
for(int i=0;i<n;i++)
{
//输出等差数列,注意空格
cout<<ans+i*ansc;
if(i!=n-1) cout<<" ";
}
}
else if(ans==0)//没有答案直接输出最后一个素数
{
cout<<st.back();
}
return 0;
}
7-5 实验室使用排期 (25 分)
受新冠疫情影响,当前大家的活动都必须注意保持充分的社交距离,国家实验室的使用也同样受到了严格的限制。假设规定任何一个时间点上,实验室内最多只能有 1 个人,且每个人都必须提前申请实验室的使用,只有申请被批准后才能进入。现给定一批第二天的实验室使用申请,你需要写个程序自动审批,使得能够被批准的申请数量最大化。
输入格式:
输入第一行首先给出一个正整数
N
(
≤
2
×
1
0
3
)
N(≤2×10^3)
N(≤2×103),为申请总量。随后 N 行,每行按以下格式给出申请信息:
hh:mm:ss hh:mm:ss
其中 hh:mm:ss 表示一天内的时间点“小时:分钟:秒钟”,最早从 00:00:00 开始,最晚到 23:59:59 结束。第一个时间点为进入实验室的时间,第二个是离开时间。题目保证离开时间在进入时间之后。
注意所有时间都在一天之内。时间按 24 小时显示。
输出格式:
在一行中输出能够被批准的最大申请数量。
输入样例:
7
18:00:01 23:07:01
04:09:59 11:30:08
11:35:50 13:00:00
23:45:00 23:55:50
13:00:00 17:11:22
06:30:50 11:42:01
17:30:00 23:50:00
输出样例:
5
样例解释:
除了最后两个申请,其它都可以被批准。
解题思路: 首先面对输入格式,选择将时间化为分钟数,方便比较(由于是考试期间就选择无脑一点的方式输入了)。接下来用了动态规划算法。动态规划的过程详见注释。
#include<bits/stdc++.h>
using namespace std;
struct timen
{
int start,end;
}a[2005];
bool cmp(const timen & a,const timen & b)
{
return a.start<b.start;
}
int main()
{
int dp[2005]={0};
dp[0]=1;//dp数组初始化
int n;
cin>>n;
for(int i=0;i<n;i++)//输入处理
{
char c;
int q,w,e;
cin>>q>>c>>w>>c>>e;
a[i].start=q*3600+w*60+e;
cin>>q>>c>>w>>c>>e;
a[i].end=q*3600+w*60+e;
}
sort(a,a+n,cmp);//按开始时间排序
int maxn=1;//存放当日可接纳的最大人数,该数至少是1
for(int i=1;i<n;i++)
//从第二项开始遍历。确定如果接受该项预约的话,
//本日零点到该项结束这段时间内最大能让多少人做上实验。
{
for(int j=0;j<i;j++)//从第一项开始找能符合的
{
if(a[i].start>=a[j].end) dp[i]=max(dp[i],dp[j]);
//判断,如果a[j]项的结束时间小于等于a[i]项的开始时间
//则a[j]项之后可以做a[i]项
//那么a[i]项就可以继承a[j]项最大能做的项数
//而项数有很多,可能前面有的项符合但是比该项能做的总数目少
//所以要用max函数来比较,取最大值。
}
dp[i]++;//dp[]数组初始都是0,要给自己这一项+1。
if(maxn<dp[i]) maxn=dp[i];//随时更新整个数组的最大值
}
if(n==0)//特判
{
cout<<0;
return 0;
}
cout<<maxn;
return 0;
}
希望我的题解能对你有所帮助(・∀・)