2019年3月浙大考研机试题解

2019年3月浙大考研机试题解

说明:增加了难度标明,纯属个人感觉,0-5难度依次增加

第一题:Conway’s Conjecture(难度:1.5)

题目:
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

Note:

本题类似1059,都是算质因子的,感觉今年3月无论PAT还是机试都能在往年真题找到一些影子,这也是一个刷题的方向吧

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> ans,fac;
ll n;
string str;
bool isprime(ll a)
{
    if(a<=1) return false;
    ll sqr=(ll)sqrt(1.0*a);
    for(ll i=2;i<=sqr;i++) if(a%i==0) return false;
    return true;
}
int main()
{
    cin>>n;
    if(n==1||n==0) { printf("%lld\nNo",n); return 0; }
    for(ll i=2;i<=n;i++) if(isprime(i)) fac.push_back(i);
    for(int i=0;i<fac.size();i++)
    {
        int cnt=0;
        while(n%fac[i]==0)
        {
            cnt++;
            n/=fac[i];
        }
        if(cnt>0) ans.push_back(fac[i]);
        if(cnt>1) ans.push_back(cnt);
    }
    for(int i=0;i<ans.size();i++) str+=to_string(ans[i]);
    ll res=stoll(str);
    if(isprime(res)) printf("%lld\nYes",res);
    else printf("%lld\nNo",res);
    return 0;
}

第二题:Play with Linked List(难度:1.8)

题目:
Given a singly linked list L​1→L​2→⋯→Ln−1 →Ln and an integer 1≤k<n, you are supposed to rearrange the links to obtain a list like L​k→Ln→Lk−1→Ln−1→⋯. For example, given L being 1→2→3→4→5→6 and k=4, you must output 4→6→3→5→2→1.
Input Specification:
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤10^​5) which is the total number of nodes, and an integer 1≤k<n where n is the number of nodes in the linked list. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

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

Note:
本题是2019年408数据结构真题改编的,每年3月机试都会有当年408算法题的,所以准备三月份机试的大佬们要注意哦,我写的略微麻烦,欢迎有更好想法的大佬指正

AC代码:

#include <bits/stdc++.h>
using namespace std;
struct Node{
    int add,data,next;
    int flag;
    int num;
}node[100000];
int n,st,k,add,data,cnt;
bool cmp(Node a,Node b)
{
    if(a.flag!=b.flag) return a.flag>b.flag;
    else return a.num<b.num;
}
int main()
{
    cin>>st>>n>>k;
    for(int i=0;i<n;i++)
    {
        cin>>add;
        node[add].add=add;
        cin>>node[add].data>>node[add].next;
    }
    for(int p=st;p!=-1;p=node[p].next)
    {
        node[p].flag=1;
        node[p].num=cnt++;
    }
    sort(node,node+100000,cmp);
    int index=cnt-1;
    if(cnt-k==k)
    {
        for(int i=k-1;i>=0;i--)
        {
            printf("%05d %d %05d\n",node[i].add,node[i].data,node[index].add);
            printf("%05d %d",node[index].add,node[index].data);
            index--;
            if(i==0) printf(" -1");
            else printf(" %05d\n",node[i-1].add);
        }
    }
    else if(k>cnt-k)
    {
        for(int i=k-1;i>=0;i--)
        {
            printf("%05d %d ",node[i].add,node[i].data);
            if(index>k-1)
            {
                printf("%05d\n",node[index].add);
                printf("%05d %d %05d\n",node[index].add,node[index].data,node[i-1].add);
                index--;
            }
            else if(i==0) printf("-1");
            else printf("%05d\n",node[i-1].add);
        }
    }
    else if(k<cnt-k)
    {
        for(int i=k-1;i>=0;i--)
        {
            printf("%05d %d %05d\n",node[i].add,node[i].data,node[index].add);
            printf("%05d %d ",node[index].add,node[index].data);
            index--;
            if(i!=0) printf("%05d\n",node[i-1].add);
            else printf("%05d\n",node[index].add);
        }
        for(int i=index;i>k-1;i--)
        {
            printf("%05d %d ",node[i].add,node[i].data);
            if(i==k) printf("-1");
            else printf("%05d\n",node[i-1].add);
        }
    }
    return 0;
}

附赠一个晴神模拟题,这个就是真题本题了

题目:
给定一条单链表,将链表结点进行头尾交错重新排序,即如果一条单链表为 L1 -> L2 -> … -> L(n-1) -> Ln ,那么重新排序完的结果是 L1 -> Ln -> L2 -> L(n-1) -> L3 -> L(n-2) -> …

输入:
每个输入文件中一组数据。
第一行给出结点的总个数N(0<N<10^5)和单链表的第一个结点的地址。所有结点的地址要么是一个五位正整数,要么是用-1表示的空地址NULL。然后是N行,表示N个结点,每行的格式为
Address Data Next
其中Address为结点地址(不足5位的高位用零填充至5位),Data为结点的数据域(绝对值不超过10^5的整数),Next为结点的指针域(即下一个结点的地址)。数据保证Address不等于-1。

输出:
输出按题目要求重新排序后的单链表。第一行为重新排序后单链表上结点的个数、第一个结点的地址。
之后每行一个结点,输出格式与输入相同,结点输出顺序为单链表连接顺序。

Sample Input
5 11111
33333 0 44444
22222 2 33333
11111 5 22222
05689 8 -1
44444 6 05689

Sample Output
5 11111
11111 5 05689
05689 8 22222
22222 2 44444
44444 6 33333
33333 0 -1

参考代码:

#include <bits/stdc++.h>
using namespace std;
struct Node{
	int add,data,next;
	int flag,num;
}node[100000];
int add,data,n,st,cnt;
bool cmp(Node a,Node b)
{
	if(a.flag!=b.flag) return a.flag>b.flag;
	else return a.num<b.num;
}
int main()
{
	cin>>n>>st;
	for(int i=0;i<n;i++)
	{
		cin>>add;
		node[add].add=add;
		cin>>node[add].data>>node[add].next;
	}
	for(int p=st;p!=-1;p=node[p].next)
	{
		node[p].num=cnt++;
		node[p].flag=1;
	}
	sort(node,node+100000,cmp);
	if(cnt==0) printf("0 -1");
	else printf("%d %05d\n",cnt,node[0].add);
	if(cnt==1) printf("%05d %d -1",node[0].add,node[add].data);
	for(int i=0;i<cnt/2;i++)
	{
		if(i!=cnt/2-1)
		{
			printf("%05d %d %05d\n",node[i].add,node[i].data,node[cnt-i-1].add);
			printf("%05d %d %05d\n",node[cnt-i-1].add,node[cnt-i-1].data,node[i+1].add);
		}
		else if(cnt%2==0)
		{
			printf("%05d %d %05d\n",node[i].add,node[i].data,node[cnt-i-1].add);
			printf("%05d %d -1\n",node[cnt-i-1].add,node[cnt-i-1].data);
		}
		else
		{
			printf("%05d %d %05d\n",node[i].add,node[i].data,node[cnt-i-1].add);
			printf("%05d %d %05d\n",node[cnt-i-1].add,node[cnt-i-1].data,node[i+1].add);
			printf("%05d %d -1\n",node[i+1].add,node[i+1].data);
		}
	}
	return 0;
}

第三题:Unsuccessful Searches(难度:1.5)

题目:在这里插入图片描述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.

小插曲:
这道题并不难,但是DS忘完了,刚开始手算都不会,有点惨。重新温习了一下DS中查找的部分一次性AC了(尴尬.ipg)

AC代码:

#include <bits/stdc++.h>
using namespace std;
int tsize,n,m,data,ans,hasht[1001];
int main()
{
    cin>>tsize>>m>>n;
    for(int i=0;i<n;i++)
    {
        cin>>data;
        for(int index=data%m;index<tsize;index++)
        {
            if(hasht[index]==0)
            {
                hasht[index]=1;
                break;
            }
            if(index==tsize-1)
            {
                for(int j=0;j<data%m;j++) if(hasht[j]==0) { hasht[j]=1; break; }
            }
        }
    }
    for(int i=0;i<m;i++)
    {
        int cnt=0;
        for(int j=i;j<tsize;j++)
        {
            cnt++;
            if(hasht[j]==0) break;
            if(j==tsize-1)
            {
                for(int step=0;step<=i;step++)
                {
                    cnt++;
                    if(hasht[step]==0) break;
                }
            }
        }
        ans += cnt;
    }
    printf("%.1f",ans*1.0/m);
    return 0;
}

第四题:Ambulance Dispatch(难度:4.0)

题目:
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 Ns(≤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 Ns, and the ambulance dispatch centers are numbered from A−1 to A−Na .

The next line gives Na 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

Note:
有点难,跟1072加油站的那道题目有一些相像,都是循环Dijkstra,不同的是本题需要保存每一个急救中心到到出事地点的路径,最开始想到的添加超级源点,每查询一个出事点就做Na个Dijkstra,有一个点超时,后来Floyd算法还是超时(其实1000个点根本不可能Floyd),最后参考了一位大佬的代码恍然大悟。。。。。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1111;
const int inf=0x3fffffff;
int G[maxn][maxn];
int d[maxn][maxn];//记录任意两点间的最短距离(实际只需用到d[ns+1][0]-d[ns+na][maxn],可以把数组定义小一点避免超内存)
int path[maxn][maxn];//path[a][b]记录a(源点)到b的路径(同上,第一维只需ns+1到ns+na)
int num[maxn][maxn];//num[a][b]记录a到b的路径上经过的街道数(同上)
int ns,na,m,ed,avail[12],vis[maxn];
void Dijkstra(int s)
{
	fill(d[s],d[s]+maxn,inf);
	fill(num[s],num[s]+maxn,inf);
	d[s][s]=0;
	num[s][s]=0;
    path[s][s]=s;
	for(int i=0;i<ns+na;i++)
	{
		int u=-1,MIN=inf;
		for(int j=1;j<=ns+na;j++)
		{
			if(vis[j]==0&&d[s][j]<MIN)
			{
				u=j;
				MIN=d[s][j];
			}
		}
		if(u==-1) return;
		vis[u]=1;
		for(int v=1;v<=ns+na;v++)
		{
			if(vis[v]==0&&G[u][v]!=0)
			{
				if(d[s][u]+G[u][v]<d[s][v])
				{
					d[s][v]=d[s][u]+G[u][v];
					num[s][v]=num[s][u]+1;
					path[s][v]=u;
				}
				else if(d[s][v]==d[s][u]+G[u][v]&&num[s][v]>=num[s][u]+1)
				{
					num[s][v]=num[s][u]+1;
					path[s][v]=u;
				}
			}
		}
	}
}
void DFS(int s,int index)
{
	if(s==index) return;
	DFS(s,path[s][index]);
    if(index>ns) printf(" A-%d",index-ns);
    else printf(" %d",index);
}
int getid(string str)
{
	if(isdigit(str[0])) return stoi(str);
	return ns+stoi(str.substr(2));
}
int main()
{
	cin>>ns>>na;
	for(int i=1;i<=na;i++) cin>>avail[i];
	cin>>m;
	string str1,str2;
	int u,v,w;
	for(int i=0;i<m;i++)
	{
		cin>>str1>>str2>>w;
		u=getid(str1);
		v=getid(str2);
		G[u][v]=G[v][u]=w;
	}
	for(int i=ns+1;i<=ns+na;i++)
	{
		Dijkstra(i);
		fill(vis,vis+maxn,0);
	}
	cin>>m;
	while(m--)
	{
		cin>>ed;
		int shortest=inf,st=-1,maxsum=-1,mins=inf;//分别表示最短距离,起点,最大可用车辆,最少路过街道
		for(int i=ns+1;i<=ns+na;i++)
		{
			if(avail[i-ns]<=0) continue;
			if(d[i][ed]<shortest)
			{
				shortest=d[i][ed];
				st=i;
				maxsum=avail[i-ns];
				mins=num[i][ed];
			}
			else if(d[i][ed]==shortest&&shortest!=inf)
			{
				if(avail[i-ns]>maxsum||(avail[i-ns]==maxsum&&mins>num[i][ed]))
				{
					st=i;
					maxsum=avail[i-ns];
					mins=num[i][ed];
				}
			}
		}
		if(st==-1) printf("All Busy\n");
		else
		{
            printf("A-%d",st-ns);
			DFS(st,ed);
			printf("\n%d\n",d[st][ed]);
			avail[st-ns]--;
		} 
	}
	return 0;
}
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值