【PTA】浙江大学计算机与软件学院2019年考研复试上机自测

个人学习记录,代码难免不尽人意。

呃,今天做了做19年的复试上机题,死在hash表上了,后面详细解释。心态要好,心态要好

7-1 Conway's Conjecture

John Horton Conway, a British mathematician active in recreational mathematics, proposed a conjecture in 2014: arrange the factors of any given number in ascending order, and pull the exponents down, we can get another number. Keep doing so we must end up at a prime number. For example:

18=2×3^2^

232=2^3^×29

2329=17×137

17137 is a prime.

Now you are supposed to write a program to make one step verification of this conjecture. That is, for any given positive integer N, you must factorize it, and then test if the number obtained from its factors is a prime.

By the way, this conjecture has been proven false by James Davis, who has discovered a counter example: 135323853961879=13×53 2 ×3853×96179. Alas ...

Input Specification:

Each input file contains one test case which gives a positive integer N (<10 5 ).

Output Specification:

For each case, first print in a line the number obtained from N's factors. The in the next line, print Yes if the above number is a prime, or No if not.

Sample Input 1:

2329

Sample Output 1:

17137

Yes

Sample Input 2:

124

Sample Output 2:

2231

No

Sample Input 3:

87516

Sample Output 3:

2232111317

No

19分代码

cpp 复制代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<map>
#include<string>
#include<stack>
using namespace std;
bool isprime(long long n){
	if(n<=1) return false;
	int mid=(int)sqrt(1.0*n);
	for(int i=2;i<=mid;i++){
		if(n%i==0) return false;
	}
	return true;
}
const int maxn=10010;
map<int,int> mp;
string tostring(int n){
	string num;
	stack<int> s;
	while(n!=0){
		int a=n%10;
		n=n/10;
		s.push(a);
	}
	while(!s.empty()){
		int a=s.top();
		s.pop();
		num+=a+'0';
	}
	return num;
}
long long toint(string s){
	long long num=0;
	for(int i=0;i<s.size();i++){
		num=num*10+s[i]-'0'; 
//		cout << num <<endl;
	}
	return num;
}
int main(){
	int n;
	scanf("%d",&n);
	int mid=(int)sqrt(1.0*n);
	for(int i=2;i<=mid;i++){
		while(n%i==0&&isprime(i)){
			if(mp.find(i)==mp.end()){
			 mp.insert(make_pair(i,1));}
			else{
				mp[i]++;
			} 
			n/=i;
		}
	}

	if(n!=1){
		mp.insert(make_pair(n,1));
	}
	string num;
	for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++){
//		cout << it->first <<"  "<<it->second << endl;
		
		if(it->second==1){
			string temp=tostring(it->first);
			num+=temp;
		}
		else{
			
			num+=tostring(it->first);
            num+=tostring(it->second);
		}
	}
	long long res;
	res=toint(num);
	printf("%lld\n",res);
	if(isprime(res)){
		printf("Yes\n");
	}
	else printf("No\n");
 
} 

挺简单的一道题,我估计是我忘记处理特殊情况了扣了一分,当输入等于1的时候应该直接输出1 NO才对。

7-2 Play with Linked List

Address Data Next

where Address is the position of the node, Data is a positive integer no more than 10

5

, and Next is the position of the next node. It is guaranteed that there are at least two nodes on the list.

Output Specification:

For each case, output in order the resulting linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:

00100 6 4

00000 4 99999

00100 1 12309

68237 6 -1

33218 3 00000

99999 5 68237

12309 2 33218

Sample Output:

00000 4 68237

68237 6 33218

33218 3 99999

99999 5 12309

12309 2 00100

00100 1 -1

cpp 复制代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<map>
#include<string>
#include<stack>
using namespace std;
const int maxn=100010;
struct node{
	int address;
	int data;
	int next;
	int before;
}Node[maxn];
node temp[maxn];
int main(){
	int begin,n,k;
	scanf("%d %d %d",&begin,&n,&k);
	for(int i=0;i<n;i++){
		int address,data,next;
		scanf("%d %d %d",&address,&data,&next);

		Node[address].address=address;
		Node[address].data=data;
		Node[address].next=next;
	}
	int op=begin,be=begin;
	Node[op].before=-1;
	op=Node[op].next;
	while(op!=-1){
		Node[op].before=be;
		be=op;
		op=Node[op].next;
	}
	op=begin;
	int index1,index2;
	int cnt=0;
	while(op!=-1){
	      cnt++;
	      if(cnt==k){
	      	index1=op;
		  }
		  if(Node[op].next==-1){
		  	index2=op;
		  }
		  op=Node[op].next;
	}
	bool flag=true;
	cnt=0;
	int tag=index1;
	while(index1!=-1&&index2!=tag){
		if(flag){
			temp[cnt++]=Node[index1];
			index1=Node[index1].before;
			flag=false;
		}
		else{
			temp[cnt++]=Node[index2];
			index2=Node[index2].before;
			flag=true;
		}
	}
	while(index1!=-1){
		temp[cnt++]=Node[index1];
		index1=Node[index1].before;
	}
	while(index2!=tag){
		temp[cnt++]=Node[index2];
		index2=Node[index2].before;
	}
	for(int i=0;i<cnt;i++){
		if(i!=cnt-1){
			printf("%05d %d %05d\n",temp[i].address,temp[i].data,temp[i+1].address);
		}
		else{
			printf("%05d %d -1\n",temp[i].address,temp[i].data);
		}
	}
} 

比较简单的一道题,我采用了双向链表来做的,找到第k个节点和最后一个节点然后开始从后往前遍历并存储到一个新的静态链表中。

7-3 Unsuccessful Searches

The above figure is a question from GRE-CS 2018. It states:

Given an initially empty hash table HT of size 11. The hash function is H(key)=key%7, with linear probing used to resolve the collisions. Now hash the keys 87, 40, 30, 6, 11, 22, 98 and 20 one by one into HT. What is the average search time for unsuccessful searches?

The answer is 6.

Now you are supposed to write a program to solve this kind of problems.

Input Specification:

Each input file contains one test case. For each case, the first line gives 3 positive integers TSize (≤10

3

, the table size), M (≤TSize, the divisor in the hash function), and N (≤TSize, the number of integers to be inserted). Then N non-negative integers (≤10

4

) are given in the next line, separated by spaces.

Output Specification:

Print in a line the average search time for unsuccessful searches, after hashing the N integers into the table. The answer must be accurate up to 1 decimal place.

Sample Input 1:

11 7 8

87 40 30 6 11 22 98 20

Sample Output 1:

6.0

Sample Input 2:

3 3 3

81 2 5

Sample Output 2:

4.0

Note: In sample 2, the last test of the original position counts as well.

别人的代码,这道题当时我没弄懂

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
	int tsize,m,n,num;
	cin>>tsize>>m>>n;
	vector<int> rec(tsize,-1);
	for(int i=0;i<n;i++){
		cin>>num;
		for(int j = 0; j < tsize; j++){
            int pos = (num % m + j) % tsize;
            if(rec[pos] == -1){
                rec[pos] = num;
                break;
            }
        }		
	}
	double sum = 0;
	//根据哈希函数地址为MODm,因此任何一个数经散列函数计算以后的初始地址只可能在0~m-1的位置
    for(int i = 0; i < m; i++){
        for(int j = 0; j <= tsize; j++){
            sum++;	//计算到此位置离空位置的距离
			//找到空位置  
            int pos = (i + j) % tsize;
            if(rec[pos] == -1){
                break;
            }
        }
    }
	printf("%.1f", sum/m);
	return 0;
}

这道题让我没弄懂什么意思,后来我才明白了处理冲突的函数和hash散列函数不是一个函数!

散列函数是第一次用来求pos: x % M , 即题中的 H(Key) = key % 7

而冲突处理函数是针对表长的,可以散列到整张表中,nex = (pos + di) % TSize, 即题中的 nex = (pos + i ) % 11。

然后就是平均查找失败长度 的概念了,这个我们需要知道(也是一个坑,之前犯过):查找到hash表为空 的时候就可以判断查找失败了!如果一直不为空的话需要额外加一次查找次数,题目中说了 。然后平均查找失败长度 就是在0~m-1之间(因为hash散列函数只能得到这个范围的结果)处理,每个节点向后查询,直到查找到hash表为空 或者Tsize次,然后所有次数除以节点个数就是我们最终想要的答案了。

这道题重点在于知道散列函数和冲突处理函数的模数不一定相同。

7-4 Ambulance Dispatch

Given the map of a city, with all the ambulance dispatch centers (救护车派遣中心) and all the pick-up spots marked. You are supposed to write a program to process the emergency calls. It is assumed that the callers are waiting at some pick-up spot. You must inform the nearest (that is, to take the minimum time to reach the spot) dispatch center if that center has at least one ambulance available. Note: a center without any ambulance must not be considered.

In case your options are not unique, inform the one with the largest number of ambulances available. If there is still a tie, choose the one that can pass the least number of streets to reach the spot, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive integers N

s

(≤10

3

) and N

a

(≤10), which are the total number of pick-up spots and the number of ambulance dispatch centers, respectively. Hence the pick-up spots are numbered from 1 to N

s

, and the ambulance dispatch centers are numbered from A−1 to A−N

a

.

The next line gives N

a

non-negative integers, where the i-th integer is the number of available ambulances at the i-th center. All the integers are no larger than 100.

In the next line a positive number M (≤10

4

) is given as the number of streets connecting the spots and the centers. Then M lines follow, each describes a street by giving the indices of the spots or centers at the two ends, followed by the time taken to pass this street, which is a positive integer no larger than 100.

Finally the number of emergency calls, K, is given as a positive integer no larger than 10

3

, followed by K indices of pick-up spots.

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

Output Specification:

For each of the K calls, first print in a line the path from the center that must send an ambulance to the calling spot. All the nodes must be separated by exactly one space and there must be no extra space at the beginning or the end of the line. Then print the minimum time taken to reach the spot in the next line. It is assumed that the center will send an ambulance after each call. If no ambulance is available, just print All Busy in a line. It is guaranteed that all the spots are connected to all the centers.

Sample Input:

7 3

3 2 2

16

A-1 2 4

A-1 3 2

3 A-2 1

4 A-3 1

A-1 4 3

6 7 1

1 7 3

1 3 3

3 4 1

6 A-3 5

6 5 2

5 7 1

A-2 7 5

A-2 1 1

3 5 1

5 A-3 2

8

6 7 5 4 6 4 3 2

Sample Output:

A-3 5 6

4

A-2 3 5 7

3

A-3 5

2

A-2 3 4

2

A-1 3 5 6

5

A-1 4

3

A-1 3

2

All Busy

20分代码:

cpp 复制代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<map>
#include<string>
#include<vector>
using namespace std;
const int maxn=1010;
const int INF=1000000000;
int G[maxn][maxn];
int nums[15];
int d[maxn];
bool visit[maxn];
vector<int> pre[maxn];
int toint(string s){
	int num=0;
	for(int i=0;i<s.size();i++){
		num=num*10+s[i]-'0';
	}
	return num;
}
void dijkstra(int begin,int n){
	for(int i=1;i<=n;i++){
		pre[i].clear();
	}
	fill(d,d+maxn,INF);
	fill(visit,visit+maxn,false);
	d[begin]=0;
	for(int i=0;i<n;i++){
		int u=-1,min=INF;
		for(int j=1;j<=n;j++){
			if(!visit[j]&&d[j]<min){
				u=j;
				min=d[j];
			}
		}
		if(u==-1) return;
		visit[u]=true;
		for(int j=1;j<=n;j++){
			if(!visit[j]&&G[u][j]!=INF){
				if(d[j]>G[u][j]+d[u]){
					d[j]=G[u][j]+d[u];
				 pre[j].clear();
				 pre[j].push_back(u);
				}
			}
		}
	}
}
vector<int> path,temp;
int streets=0;
void dfs(int st,int ed){
	if(ed==st){
		temp.push_back(ed);
		if(path.empty()){
			path=temp;
			streets=temp.size();
		}
		else{
			int street=temp.size();
			if(streets>street){
				path=temp;
				streets=street;
			}
		}
		temp.pop_back();
		return;
	}
	temp.push_back(ed);
	for(int i=0;i<pre[ed].size();i++){
		dfs(st,pre[ed][i]);
	}
	temp.pop_back();
}
int main(){
	for(int i=0;i<maxn;i++){
		for(int j=0;j<maxn;j++){
			G[i][j]=INF;
		}
	}
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d",&nums[i]);
	}
	int k;
	scanf("%d",&k);
	for(int i=0;i<k;i++){
		string a,b;
		int a1,b1,dis;
		cin >> a >> b>> dis;
		if(a[0]=='A'){
			a1=toint(a.substr(2,a.size()-2))+n;
			b1=toint(b);
		}
		else if(b[0]=='A'){
			b1=toint(b.substr(2,b.size()-2))+n;
			a1=toint(a);
		}
		else{
			a1=toint(a);
			b1=toint(b); 
		}
	
		G[a1][b1]=dis;
		G[b1][a1]=dis;
	}
	scanf("%d",&k);
	for(int p=0;p<k;p++){
		int ed;
		scanf("%d",&ed);
		dijkstra(ed,n+m);
		
		int end=-1;int min=INF;
		int street=0;
		for(int j=n+1;j<=n+m;j++){
			if(nums[j-n]>0){
				if(d[j]<min){
					end=j;
					min=d[j];
				}
				else if(d[j]==min){
					if(nums[end-n]<nums[j-n]){
						end=j;
					}
					else if(nums[end-n]==nums[j-n]){
						path.clear();temp.clear();streets=0;
						dfs(ed,end);
						street=streets;
						path.clear();temp.clear();streets=0;
						dfs(ed,j);
						if(street>streets){
							end=j;
							street=streets;
						}
					}
				}
			}
		}
		if(end==-1){
			printf("All Busy\n");
			continue;
		}
		path.clear();temp.clear();streets=0;
		dfs(ed,end);
		nums[end-n]--;
		int time=0;
		for(int i=0;i<path.size()-1;i++){
			time+=G[path[i]][path[i+1]];
		}
		for(int i=0;i<path.size();i++){
			if(path[i]>n){
				printf("A-%d",path[i]-n);
			}
			else printf("%d",path[i]);
			if(i!=path.size()-1) printf(" ");
			else printf("\n");	
		}
		printf("%d\n",time);
	}
	
} 

小时候最害怕的一题,有两个测试点段错误,检查不出问题来了。

后来想想这道题可以用floyd来做,比每次都调用dijkstra逻辑上要清晰许多。

相关推荐
1 9 J5 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
passer__jw7672 小时前
【LeetCode】【算法】3. 无重复字符的最长子串
算法·leetcode
passer__jw7672 小时前
【LeetCode】【算法】21. 合并两个有序链表
算法·leetcode·链表
sweetheart7-72 小时前
LeetCode22. 括号生成(2024冬季每日一题 2)
算法·深度优先·力扣·dfs·左右括号匹配
李元豪3 小时前
【智鹿空间】c++实现了一个简单的链表数据结构 MyList,其中包含基本的 Get 和 Modify 操作,
数据结构·c++·链表
UestcXiye4 小时前
《TCP/IP网络编程》学习笔记 | Chapter 9:套接字的多种可选项
c++·计算机网络·ip·tcp
一丝晨光4 小时前
编译器、IDE对C/C++新标准的支持
c语言·开发语言·c++·ide·msvc·visual studio·gcc
景鹤4 小时前
【算法】递归+回溯+剪枝:78.子集
算法·机器学习·剪枝
_OLi_5 小时前
力扣 LeetCode 704. 二分查找(Day1:数组)
算法·leetcode·职场和发展
丶Darling.5 小时前
Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)
c++·算法·动态规划·记忆化搜索·回溯