2022PAT甲级冬季满分题解

新人求点赞(^_^)

A-1 Reduction of Proper Fractions

Proper Fraction(真分数)is a fraction where the numerator(分子)is less than the denominator(分母). To reduce a fraction, we are supposed to cross out any common factors between the numerator and the denominator.

Here is another way to do the reduction: simply cross out any common digits. In most of the cases, this way cannot give the correct result. However, sometimes it happends to work! For example: 26/65 = 2/5 where 6 is crossed out.

Now given a proper fraction, you are supposed to tell if this simple reduction works or not.

Input Specification:

Each input file contains one test case, with the numerator a and the denominator b of the proper fraction given in a line, separated by a space. It is guaranteed that 0<a<b≤105.

Output Specification:

For each test case, print in a line both fractions before and after the simple reduction. If they are equal, put a = between them; else put != instead. The format is either a/b = c/d or a/b != c/d.

#include<bits/stdc++.h>
using namespace std;
int a,b,aa,bb,tt,btt[20],att[20],bbtt[20],aatt[20];
int ta,at,b1,bbb,suma,sumb;
int main() {
	cin>>a>>b;
	aa=a;
	bb=b;
	while(bb) {
		tt++;
		btt[tt]=bb%10;
		bb/=10;
	}
	while(aa) {
		ta++;
		at=aa%10;
		aa/=10;
		b1=0;
		for(int i=tt; i>=1; i--)
			if(btt[i]==at&&bbtt[i]!=1) {
				bbtt[i]=1;
				aatt[ta]=1;
				break;
			}
		att[ta]=at;
	}
	for(int i=tt; i>=1; i--) {
		if(!bbtt[i])sumb=btt[i]+sumb*10;
	}
	for(int i=ta; i>=1; i--) {
		if(!aatt[i])suma=att[i]+suma*10;
	}
	if(suma*b==sumb*a)bbb=1;
	printf("%d/%d ",a,b);
	if(!bbb||(suma==0&&sumb==0))printf("!");
	printf("= %d/%d",suma,sumb);
//	else printf("= /%d",sumb);
	return 0;
}
//39/195 = 3/15
//39/195 = 3/15


A-2 Luggage Pickup

When a flight arrives, the passengers will go to the Arrivals area to pick up their baggage from a luggage conveyor belt (行李传送带).

Now assume that we have a special airport that has only one pickup window for each conveyor belt. The passengers are asked to line up to pick up their luggage one by one at the window. But if one arrives at the window yet finds out that one is not the owner of that luggage, one will have to move to the end of the queue and wait for the next turn. At the mean time, the luggage at the window will wait until its owner picks it up. Suppose that each turn takes 1 minute, your job is to calculate the total time taken to clear the conveyor belt, and the average waiting time for the passengers.

For example, assume that luggage i belongs to passenger i. If the luggage come in order 1, 2, 3, and the passengers come in order 2, 1, 3. Luggage 1 will wait for 2 minutes to be picked up by passenger 1. Then the luggage queue contains 2 and 3, and the passenger queue contains 3 and 2. So luggage 2 will wait for 2 minutes to be picked up by passenger 2. And finally 3 is done at the 5th minute. The average waiting time for the passengers is (2+4+5)/3≈3.7.

Input Specification:

Each input file contains one test case. The first line gives a positive integer N (≤103). Then N numbers are given in the next line, which is a permutation of the integers in [1,N], representing the passenger queue. Here we are assuming that the luggage queue is in order of 1, 2, ..., N, and the i-th luggage belongs to passenger i.

All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in a line the total time taken to clear the conveyor belt, and the average waiting time for the passengers (output 1 decimal place). The numbers must be separated by 1 space, and there must be no extra space at the beginning or the end of the line.

#include<bits/stdc++.h>
using namespace std;
int n,aa[1005],a[1005],b1,sum;
int main() {
	cin>>n;
	for(int i=0; i<=n-1; i++)
		cin>>a[i];
	int mod,idx=0,idx2,sum2=0;
	for(int i=0; i<n-1; i++) {
		b1=0;
		mod=n-i;
		for(int j=idx; j<idx+n-i; j++) {
			int jj=j%mod;

			if(a[jj]==i+1) {
				b1=1;
				sum+=(jj-idx+mod)%mod+1;
				sum2+=((jj-idx+mod)%mod+1)*(n-i);
				idx2=jj;
				idx=jj%(mod-1);
				break;
			}

		}
		for(int j=idx2; j<=mod-1; j++) {
			a[j]=a[j+1];
		}
	}
	sum+=1;
	sum2++;
	printf("%d %.1f",sum,sum2/(n*1.0));
	return 0;
}

A-3 Articulation Points

In graph theory, given a connected graph G, the vertices whose removal would disconnect G are known as articulation points. For example, vertices 1, 3, 5, and 7 are the articulation points in the graph shown by the above figure (also given by the sample input).

It is a bit complicated to find the articulation points. Here you are only asked to check if a given vertex is an articulation point or not.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 positive integers: N (≤103), M (≤104), and K (≤100), which are the number of vertices, the number of edges, and the number of queries, respectively. Then M lines follow, each gives an undirected edge in the format:

v1 v2

where v1 and v2 are the two ends of an edge. Here we assume that all the vertices are numbered from 0 to N−1. It is guaranteed that v1 is never the same as v2, and the graph is connected.

Finally a line of queries are given, which contains K vertices to be checked. The numbers in a line are separated by spaces.

Output Specification:

Output a string of 0's and 1's in a line. That is, for each query, print 1 if the given vertex is an articulation point, or 0 if not. There must be no space between the answers.

#include<bits/stdc++.h>
using namespace std;
int n,m,k,a,b[1005],bbb,bc;
vector<int>link[1005];
void dfs(int v,int p) {
	if(b[v])return;
	b[v]=1;
	for(auto i:link[v]) {
		if(i!=p) {
			dfs(i,p);
		}
	}
}
int main() {
	cin>>n>>m>>k;
	for(int i=1; i<=m; i++) {
		scanf("%d%d",&a,&bc);
		//	e[a][b]=1;
		//	e[b][a]=1;
		link[a].push_back(bc);
		link[bc].push_back(a);
	}
	for(int i=1; i<=k; i++) {
		scanf("%d",&a);
		bbb=1;
		int j=link[a][0];

		memset(b,0,sizeof b);
		dfs(j,a);
		for(auto k:link[a])
			if(!b[k]) {
				bbb=0;
				break;
			}

		cout<<1-bbb;
	}
	return 0;
}

A-4 Check Inorder Traversals

Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can be determined by a given pair of postorder and inorder traversal sequences, or preorder and inorder traversal sequences. However, if only the postorder and preorder traversal sequences are given, the corresponding tree may no longer be unique.

Now given a pair of postorder and preorder traversal sequences, you are supposed to check a set of inorder traversal sequences, and answer whether or not they are indeed inorder traversal sequences of the tree.

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 preorder sequence and the third line gives the postorder sequence.

Then another positive integer K (≤ 10) is given, followed by K lines of inorder traversal sequences.

Each sequence consists of N positive integers. All the numbers in a line are separated by a space.

Output Specification:

For each inorder traversal sequence, print in a line Yes if it is an inorder traversal sequence of the tree, or No if not.

On the other hand, there is another possible case that the given pre- and postorder traversal sequences can NOT form any tree at all. In that case, first print in a line Are you kidding me?. Then for each inorder traversal sequence of the input, try to construct a tree with the given preorder traversal sequence, and output in a line the correct postorder traversal sequence. If it is still impossible, output You must be kidding me! instead.

#include<bits/stdc++.h>
using namespace std;
const int N=50;
int pre[N],post[N],post2[N],in[N],n,k;
int cnt=0;
int bbb=1;
int b2=1;
void bd2(int pl,int pr,int pol,int por) {
	if(pl>pr||pol>por||b2==0) {
		return;
	}
	if(pre[pl]!=post[por]) {
		b2=0;
		return;
	}
	if(pl==pr)return;
	int a=pre[pl+1];
	int tt=pol;
	while(post[tt]!=a&&tt<=por)tt++;
	if(tt>por) {
		b2=0;
		return;
	}
	bd2(pl+1,pl+tt-pol+1,pol,tt);
	bd2(pl+tt-pol+2,pr,tt+1,por-1);
}
void bd(int pl,int pr,int il,int ir) {
	if(pl>pr||il>ir||bbb==0)return;
	int a=pre[pl];
	int tt=il;
	while(in[tt]!=a&&tt<=ir)tt++;
	if(tt>ir) {
		bbb=0;
		return;
	}
	bd(pl+1,pl+tt-il,il,tt);
	bd(pl+tt-il+1,pr,tt+1,ir);
	cnt++;
	post2[cnt]=a;
}
int main() {
	cin>>n;
	for(int i=1; i<=n; i++)
		scanf("%d",&pre[i]);
	for(int i=1; i<=n; i++)
		scanf("%d",&post[i]);
	b2=1;
	bd2(1,n,1,n);
	if(!b2)
		cout<<"Are you kidding me?\n";
	cin>>k;
	for(int j=1; j<=k; j++) {
		cnt=0;
		bbb=1;
		for(int i=1; i<=n; i++)
			scanf("%d",&in[i]);

		bd(1,n,1,n);
		if(b2) {

			for(int i=1; i<=n; i++) {
				if(post[i]!=post2[i]) {
					bbb=0;
					break;
				}
			}
			if(bbb)cout<<"Yes\n";
			else cout<<"No\n";

		} else {
			if(bbb) {
				cout<<post2[1];
				for(int i=2; i<=n; i++)
					cout<<' '<<post2[i];
				cout<<endl;
			} else cout<<"You must be kidding me!\n";
		}
	}
	return 0;
}

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值