2019-PAT春季考试小结

第一次参加pat考试,大概准备了一两个月这样,主要还是参考算法笔记,然后就是狂刷模拟题,各种题型都熟悉一遍(个人感觉二叉树的建树、并查集、dfs、dijkstra比较重要一点)。进入考场后直到1点半老师才让我们动鼠标,我先试试IDE,codeblocks不知为什么找不到编译器路径,心态有点崩,最后用了dev,建议各位把考场有的ide都熟悉一下。先把字体调成自己喜欢的加上各种头文件开始答题了。第一...
摘要由CSDN通过智能技术生成

第一次参加pat考试,大概准备了一两个月这样,主要还是参考算法笔记,然后就是狂刷模拟题,各种题型都熟悉一遍(个人感觉二叉树的建树、并查集、dfs、dijkstra比较重要一点)。
进入考场后直到1点半老师才让我们动鼠标,我先试试IDE,codeblocks不知为什么找不到编译器路径,心态有点崩,最后用了dev,建议各位把考场有的ide都熟悉一下。先把字体调成自己喜欢的加上各种头文件开始答题了。第一题是关于素数的,还行;第二题是关于字符串处理的,用了个map解决;第三题找电话诈骗团伙,应该是并查集题目,但是我没用并查集,最后一个点没过去。。第四题是二叉树,先建树,再判断各种关于该树的语句是否正确,主要还是处理输入数据比较麻烦,最后也是一个点没过去。。
最大的感悟是题目要看仔细,毕竟都是英文很容易错过很小的信息,如more than、no more than之类的。

最后附上原题和考场上代码:

7-1 Sexy Primes (20 分)
Sexy primes are pairs of primes of the form (p, p+6), so-named since “sex” is the Latin word for “six”. (Quoted from http://mathworld.wolfram.com/SexyPrimes.html)
Now given an integer, you are supposed to tell if it is a sexy prime.
Input Specification:
Each input file contains one test case. Each case gives a positive integer N (≤10​8​​).
Output Specification:
For each case, print in a line Yes if N is a sexy prime, then print in the next line the other sexy prime paired with N (if the answer is not unique, output the smaller number). Or if N is not a sexy prime, print No instead, then print in the next line the smallest sexy prime which is larger than N.
Sample Input 1:

47

Sample Output 1:

Yes
41

Sample Input 2:

21

Sample Output 2:

No
23
题目大意:找 性感?素数,注意不要忘了判断n-6.

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
using namespace std;
bool isprime(int n){
	if(n<=1) return false;
	for(int i=2;i*i<=n;i++){
		if(n%i==0) return false;
	}
	return true;
}
int main() {
	int n;
	scanf("%d",&n);
	if(isprime(n)){
		if(isprime(n-6)){
		printf("Yes\n%d\n",n-6);
		return 0;
		}
		else if(isprime(n+6)){
			printf("Yes\n%d\n",n+6);
			return 0;
		}
	}
			for(int i=n+1;;i++){
				if(isprime(i)&&(isprime(i+6)||isprime(i-6))){
					printf("No\n%d\n",i);
					break;
				}
			}
	return 0;
}

7-2 Anniversary (25 分)

Zhejiang University is about to celebrate her 122th anniversary in 2019. To prepare for the celebration, the alumni association (校友会) has gathered the ID’s of all her alumni. Now your job is to write a program to count the number of alumni among all the people who come to the celebration.
Input Specification:
Each input file contains one test case. For each case, the first part is about the information of all the alumni. Given in the first line is a positive integer N (≤10​5​​). Then N lines follow, each contains an ID number of an alumnus. An ID number is a string of 18 digits or the letter X. It is guaranteed that all the ID’s are distinct.
The next part gives the information of all the people who come to the celebration. Again given in the first line is a positive integer M (≤10​5​​). Then M lines follow, each contains an ID number of a guest. It is guaranteed that all the ID’s are distinct.
Output Specification:
First print in a line the number of alumni among all the people who come to the celebration. Then in the second line, print the ID of the oldest alumnus – notice that the 7th - 14th digits of the ID gives one’s birth date. If no alumnus comes, output the ID of the oldest guest instead. It is guaranteed that such an alumnus or guest is unique.
Sample Input:

5
372928196906118710
610481197806202213
440684198612150417
13072819571002001X
150702193604190912
6
530125197901260019
150702193604190912
220221196701020034
610481197806202213
440684198612150417
370205198709275042

Sample Output:

3
150702193604190912

题目大意:相当于输出两个集合交集的元素个数,若有交集,则输出交集中人年龄最大一个,若无交集,则输出第二个集合中年龄最大的。年龄最大可以通过比较字符串第7-14位大小,越小,年龄越大。

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
using namespace std;

map<string,bool>mp;

int main() {
	int n,m;
	scanf("%d",&n);
	string str;
	for(int i=0;i<n;i++){
		cin>>str;
		mp[str]=true;
	}
	scanf("%d",&m);
	int cnt=0;
	string res1,res2;
	for(int i=0;i<m;i++){
		cin>>str;
		if(mp.find(str)!=mp.end()){
			cnt++;
			if(cnt==1){
				res1=str;
			}
			else{
				if(str.substr(6,8)<res1.substr(6,8)){
					res1=str;
				}
			}
		}
		else{
			if(res2.size()==0){
				res2=str;
				
			}
			else{
				if(str.substr(6,8)<res2.substr(6,8)){
					res2=str;
				}
			}
		}
	}
	printf("%d\n",cnt);
	if(cnt==0) cout<<res2;
	else cout<<res1;
	return 0;
}

7-3 Telefraud Detection (25 分)

Telefraud(电信诈骗) remains a common and persistent problem in our society. In some cases, unsuspecting victims lose their entire life savings. To stop this crime, you are supposed to write a program to detect those suspects from a huge amount of phone call records.

A person must be detected as a suspect if he/she makes more than K short phone calls to different people everyday, but no more than 20% of these people would call back. And more, if two suspects are calling each other, we say they might belong to the same gang. A makes a short phone call to B means that the total duration of the calls from A to B is no more than 5 minutes.
Input Specification:

Each input file contains one test case. For each case, the first line gives 3 positive integers K (≤500, the threshold(阈值) of the amount of short phone calls), N (≤10​3​​, the number of different phone numbers), and M (≤10​5​​, the number of phone call records). Then M lines of one day’s records are given, each in the format:

caller receiver duration

where caller and receiver are numbered from 1 to N, and duration is no more than 1440 minutes in a day.
Output Specification:

Print in each line all the detected suspects in a gang, in ascending order of their numbers. The gangs are printed in ascending order of their first members. The numbers in a line must be separated by exactly 1 space, and there must be no extra space at the beginning or the end of the line.

If no one is detected, output None instead.
Sample Input 1:

5 15 31
1 4 2
1 5 2
1 5 4
1 7 5
1 8 3
1 9 1
1 6 5
1 15 2
1 15 5
3 2 2
3 5 15
3 13 1
3 12 1
3 14 1
3 10 2
3 11 5
5 2 1
5 3 10
5 1 1
5 7 2
5 6 1
5 13 4
5 15 1
11 10 5
12 14 1
6 1 1
6 9 2
6 10 5
6 11 2
6 12 1
6 13 1

Sample Output 1:

3 5
6

Note: In sample 1, although 1 had 9 records, but there were 7 distinct receivers, among which 5 and 15 both had conversations lasted more than 5 minutes in total. Hence 1 had made 5 short phone calls and didn’t exceed the threshold 5, and therefore is not a suspect.
Sample Input 2:

5 7 8
1 2 1
1 3 1
1 4 1
1 5 1
1 6 1
1 7 1
2 1 1
3 1 1

Sample Output 2:

None

题目大意:找诈骗团伙,一个人打的短电话(打给一个人的总时间小于等于5)次数超过阈值同时打回来的电话不超过20%则为骗子,两个骗子相互打电话则为同伙。
这题题目看了好久,more than,no more than各种搞混,一个点没过去,19分。

#include <iostream>
#include <cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include <map>
#include<set>
using namespace std;

const int maxn = 1005;
int call[maxn][maxn]={0};
set<int>st;
int main() {
	int k,n,m;
	scanf("%d %d %d",&k,&n,&m);
	int a,b,c;
	for(int i=0;i<m;i++){
		scanf("%d%d%d",&a,&b,&c);
		call[a][b]+=c;
	}
	for(int i=1;i<=n;i++){
		int cnt1=0,cnt2=0;
		for(int j=1;j<=n;j++){
			if(i!=j){
				if(call[i][j]>0&&call[i][j]<=5){
					cnt1++;
					if(call[j][i]!=0) cnt2++;
				}
			}
		}
		float t=1.0*cnt2/cnt1;
		if(cnt1>k && t<=0.2) st.insert(i);
	}
	if(st.size()==0) printf("None\n");
	else{
		vector<vector<int> > v;
		for(set<int>::iterator it=st.begin();it!=st.end();it++){
			bool flag=false;
			for(int i=0;i<v.size();i++){
				for(int j=0;j<v[i].size();j++){
					if(call[*it][v[i][j]]!=0&&call[v[i][j]][*it]!=0){
						v[i].push_back(*it);
						flag=true;
						break;
					}
				}
				if(flag) break;
			}
			if(!flag){
				vector<int>temp(1,*it);
				v.push_back(temp);
			}
		}
		for(int i=0;i<v.size();i++){
			sort(v[i].begin(),v[i].end());
			for(int j=0;j<v[i].size();j++){
				if(j==0) printf("%d",v[i][j]);
				else printf(" %d",v[i][j]);
			}
			printf("\n");
		}
	}
	return 0;
}

7-4 Structure of a Binary Tree (30 分)

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, a binary tree can be uniquely determined.

Now given a sequence of statements about the structure of the resulting tree, you are supposed to tell if they are correct or not. A statment is one of the following:

A is the root
A and B are siblings
A is the parent of B
A is the left child of B
A is the right child of B
A and B are on the same level
It is a full tree

Note:

Two nodes are on the same level, means that they have the same depth.
A full binary tree is a tree in which every node other than the leaves has two children.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are no more than 10​3​​ and are separated by a space.

Then another positive integer M (≤30) is given, followed by M lines of statements. It is guaranteed that both A and B in the statements are in the tree.
Output Specification:

For each statement, print in a line Yes if it is correct, or No if not.
Sample Input:

9
16 7 11 32 28 2 23 8 15
16 23 7 32 11 2 28 15 8
7
15 is the root
8 and 2 are siblings
32 is the parent of 11
23 is the left child of 16
28 is the right child of 2
7 and 11 are on the same level
It is a full tree

Sample Output:

Yes
No
Yes
No
Yes
Yes
Yes

题目大意:根据中序和后序建树,再判断各个说法对不对。这题简直精污,感觉主要问题是处理输入数据。我是读入一行,根据各种字符判断,写到一半想到可以用sscanf这个强大的功能。。最后写的脑阔疼,还有一个点没过去,27分,可能哪里判断错了,等进入模拟题时再试试。

#include <iostream>
#include <cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include <map>
#include<set>
using namespace std;

const int maxn=30;
int n;
int pre[maxn],post[maxn],in[maxn];
struct node{
	node* left;
	node* right;
	int val;
	int level;
};
map<int,node*>mp;
node* create(int postl,int postr,int inl,int inr,int h){
	if(postl>postr){
        return NULL;
	}
	node* now = new node;
	now->val = post[postr];
	now->level = h;
	int i;
	for(i=inl;i<=inr;i++){
        if(in[i]==post[postr]) break;
	}
	int numLeft = i-inl;
	now->left=create(postl,postl+numLeft-1,inl,i-1,h+1);
	now->right = create(postl+numLeft,postr-1,i+1,inr,h+1);
	mp[now->val]=now;
	return now;
}

void preorder(node* root){
	if(root==NULL) return;
	cout<<root->val<<" ";
	preorder(root->left);
	preorder(root->right);
}

bool findn(node* root,node* a){
	if(root==a) return true;
	if(root==NULL) return false;
	return findn(root->left,a)||findn(root->right,a);
}


int main() {
	int m;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&post[i]);
	}
	for(int i=0;i<n;i++){
		scanf("%d",&in[i]);
	}
	node* root=create(0,n-1,0,n-1,0);
	string str;
	scanf("%d",&m);
	getchar();
	for(int i=0;i<m;i++){
		getline(cin,str);
		if(str[0]=='I'){
			queue<node*>q;
			q.push(root);
			bool flag=true;
			while(!q.empty()){
				node* now=q.front();
				q.pop();
	//			cout<<now->val<<" ";
				if(now->left&&now->right) {
					q.push(now->left);
					q.push(now->right);
				}
				else if(now->left==NULL&&now->right==NULL) continue; 
				else{
					flag=false;
					break;
				}
				
			}
			if(flag) printf("Yes\n");
			else printf("No\n");
		}
		else{
			int i=0;
			while(str[i]>='0'&&str[i]<='9'){i++;};
			int a,b;
			sscanf(str.substr(0,i).c_str(),"%d",&a);
			if(str[str.size()-1]=='t'){
				if(root==mp[a]){
					printf("Yes\n");
				}
				else{
					printf("No\n");
				}
			}
			else{
				if(str[str.size()-1]=='l'){
					sscanf(str.c_str(),"%d and %d are on the same level",&a,&b);
					if(mp[a]->level == mp[b]->level){
							printf("Yes\n");
					}
					else{
						printf("No\n");
					}
				}
				else if(str[str.size()-1]=='s'){
					sscanf(str.c_str(),"%d and %d are siblings",&a,&b);
					queue<node*>q;
					q.push(root);
					node* aa=mp[a];
					node* bb=mp[b];
					bool flag=true;
					while(!q.empty()){
						node* now=q.front();
						q.pop();
			//			cout<<now->val<<" ";
						if((now->left==aa&&now->right==bb)||(now->left==bb&&now->right==aa)) {
							break;
						}
						else if((now->left!=aa&&now->right!=bb)&&(now->left!=bb&&now->right!=aa)){
							if(now->left)	q.push(now->left);
							if(now->right)	q.push(now->right);
						}
						else{
							flag=false;
							break;
						}
					}
					if(flag) printf("Yes\n");
					else printf("No\n");
				}
				else{
					bool isp=false,isl=false,isr=false;
					for(int j=0;j<str.size();j++){
						if(str[j]=='p'){
							isp=true;
							break;
						}
						else if(str[j]=='l'){
							isl=true;
							break;
						}
						else if(str[j]=='r'){
							isr=true;
							break;
						}
					}
					if(isp){
						sscanf(str.c_str(),"%d is the parent of %d",&a,&b);
						if(mp[a]->left==mp[b]||mp[a]->right==mp[b]){
							printf("Yes\n");
						}
						else printf("No\n");
					}
					else if(isl){
						sscanf(str.c_str(),"%d is the left child of %d",&a,&b);
						if(findn(mp[b]->left,mp[a])){
							printf("Yes\n");
						}
						else printf("No\n");
					}
					else if(isr){
						sscanf(str.c_str(),"%d is the right child of %d",&a,&b);
						if(findn(mp[b]->right,mp[a])){
							printf("Yes\n");
						}
						else printf("No\n");
					}
				}
			}
		}
	}
	return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值