浙江大学计算机与软件学院2019年考研复试上机模拟练习

7-1 Conway’s Conjecture (20 分)

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=23×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×532×3853×96179. Alas …

Input Specification:
Each input file contains one test case which gives a positive integer N (<105).

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

这题大意就是把给定的数字给因式分解了,然后把指数放下来,最后看得到的数字是不是素数,有个坑点是输入为1,我这代码算是有点冗余了,不过能过就行。

代码如下:

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

bool isPrime(long long int n)
{
    if (n <= 3)
        return n > 1;
    else if (n % 6 != 1 && n % 6 != 5)
        return false;

    int sq = sqrt(n);
    for (long long int i = 5; i <= sq; i += 6)
    {
        if (n % i == 0 || n % (i + 2) == 0)
            return false;
    }
    return true;
}

int main()
{
    long long int n;
    string result;
    vector<int> rec;
    cin >> n;
    if (n == 1) // 有个测试点是1
    {
        cout << 1 << endl;
        cout << "No" << endl;
    }
    else
    {
        while (n != 1)
        {
            for (int i = 2; i <= n; i++)
            {
                if (n % i == 0)
                {
                    rec.push_back(i);
                    n /= i;
                    break;
                }
            }
        }
        result += to_string(rec[0]);
        int cnt = 1;
        for (int i = 1; i < rec.size(); i++)
        {
            if (rec[i] == rec[i - 1])
                cnt++;
            else
            {
                if (cnt > 1)
                    result += to_string(cnt);
                result += to_string(rec[i]);
                cnt = 1;
            }
        }
        if (cnt > 1)
            result += to_string(cnt);

        cout << result << endl;
        if (isPrime(stoll(result)))
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
    return 0;
}

7-2 Play with Linked List (25 分)

Given a singly linked list L1→L2→⋯→Ln-1→Ln and an integer 1≤k<n, you are supposed to rearrange the links to obtain a list like Lk→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 (≤105) 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 105, 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

代码如下:

#include <iostream>
#include <vector>
using namespace std;

struct node
{
    int addr, data, next;
} list[100005];

int main()
{
    int first, n, k, a, d, ne;
    cin >> first >> n >> k;
    for (int i = 0; i < n; i++)
    {
        cin >> a >> d >> ne;
        list[a] = {a, d, ne};
    }

    vector<node> list1, list2, result;
    for (int i = first, j = 1; i != -1; i = list[i].next, j++)
    {
        if (j > k)
            list2.push_back(list[i]);
        else
            list1.push_back(list[i]);
    }

    while (!(list1.empty() && list2.empty()))
    {
        if (!list1.empty())
        {
            result.push_back(list1.back());
            list1.pop_back();
        }
        if (!list2.empty())
        {
            result.push_back(list2.back());
            list2.pop_back();
        }
    }

    for (int i = 0; i < result.size(); i++)
    {
        printf("%05d %d ", result[i].addr, result[i].data);
        if (i != result.size() - 1)
            printf("%05d\n", result[i + 1].addr);
        else
            printf("-1\n");
    }
    return 0;
}

7-3 Unsuccessful Searches (25 分)

在这里插入图片描述
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 (≤103, 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 (≤104) 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.

这题有点怎么说不符合常规吧,得自己把两个样例推完才知道它是什么规则,第二个样例相当于是对于哈希出来每个位置都找不到元素要遍历四次,所以是3×4÷3=4.0。

代码如下:

#include <iostream>
using namespace std;

int main()
{
    int tsize, m, n, num, result = 0;
    cin >> tsize >> m >> n;
    int table[tsize];
    fill(table, table + tsize, -1);
    for (int i = 0; i < n; i++)
    {
        cin >> num;
        int key = num % m;
        for (int j = 0; j < tsize; j++)
        {
            int index = (key + j) % tsize;
            if (table[index] == -1)
            {
                table[index] = num;
                break;
            }
        }
    }

    for (int i = 0; i < m; i++)
    {
        bool flag = false; // 记录能否找到-1,找不到-1说明要找整个表,次数为tsize+1
        for (int j = 0; j < tsize; j++)
        {
            result++;
            int index = (i + j) % tsize;
            if (table[index] == -1)
            {
                flag = true;
                break;
            }
        }
        if (flag == false)
            result++;
    }
    printf("%.1f\n", result * 1.0 / m);
    return 0;
}

7-4 Ambulance Dispatch (30 分)

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(≤103) and Na(≤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 (≤104) 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 103, 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

这题考场上考到直接寄吧,最好用floyd混分,dijskra很容易逻辑不清晰调试很久。其实也不难,就是最短路径加上路径存储,然后需要注意的点就是当时间相同时选择具有救护车最多的救护站,如果救护车数目还相同那么选择所走公路条数最多的路径。最后的测试点数据量比较大,因此每次dijskra之后直接把数据保存,避免对于同一个点多次运算,哪成想优化之后还过不了,尽力只能26了,也没想到其他更好的办法,最后放个别人通过的链接吧。

代码如下(26分):

#include <iostream>
#include <vector>
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 1015;
int ns, na, m, k, call, total; // ns求救点数目,na救助站数目,m条公路,total表示总的地点数目 total = ns + na
int cars[15];
int cost[MAXN][MAXN], streets[MAXN][MAXN], pre[MAXN][MAXN], dist[MAXN][MAXN]; // cost记录路径之间时间花销,streets用于记录到达求救点要经过多少条路,pre用于路径回溯
bool visit[MAXN];
bool traversal[MAXN]; // 对于每个点只dijskra一次,避免重复遍历花费时间

bool dijskra()
{
    bool flag = false;
    for (int i = 1; i <= na; i++)
    {
        if (cars[i] != 0)
            flag = true;
    }
    if (flag == false)
        return false; // 无车
    if (traversal[call])
        return true;

    fill(visit, visit + MAXN, false);
    dist[call][call] = 0;
    for (int i = 1; i <= total; i++)
    {
        int v = -1;
        for (int j = 1; j <= total; j++)
        {
            if (visit[j] == false && (v == -1 || dist[call][j] < dist[call][v]))
                v = j;
        }

        visit[v] = true;
        for (int j = 1; j <= total; j++)
        {
            if (visit[j] == false)
            {
                if (dist[call][v] + cost[v][j] < dist[call][j])
                {
                    dist[call][j] = dist[call][v] + cost[v][j];
                    streets[call][j] = streets[call][v] + 1; // 记录路径条数
                    pre[call][j] = v;
                }
                else if (dist[call][v] + cost[v][j] == dist[call][j] && streets[call][v] + 1 < streets[call][j])
                {
                    streets[call][j] = streets[call][v] + 1;
                    pre[call][j] = v;
                }
            }
        }
    }
    traversal[call] = true;
    return flag; // 有车
}

void storePath()
{
    string s1, s2;
    int v1, v2, time;
    cin >> s1 >> s2 >> time;
    if (s1[0] == 'A')
        v1 = stoi(s1.substr(2)) + ns;
    else
        v1 = stoi(s1);
    if (s2[0] == 'A')
        v2 = stoi(s2.substr(2)) + ns;
    else
        v2 = stoi(s2);
    cost[v1][v2] = cost[v2][v1] = time;
}

int main()
{
    fill(cost[0], cost[0] + MAXN * MAXN, INF);
    fill(dist[0], dist[0] + MAXN * MAXN, INF);
    fill(streets[0], streets[0] + MAXN * MAXN, 0);
    string s1, s2;
    int v1, v2;
    cin >> ns >> na;
    total = ns + na;
    for (int i = 1; i <= na; i++)
        cin >> cars[i];
    cin >> m;
    for (int i = 0; i < m; i++)
        storePath();
    cin >> k;
    for (int i = 0; i < k; i++)
    {
        cin >> call;
        if (dijskra() == false)
            cout << "All Busy" << endl;
        else
        {

            int minTime = INF, ambulance = -1;
            for (int i = ns + 1; i <= total; i++)
            {
                if (dist[call][i] < minTime && cars[i - ns] > 0) // 首先找花费时间最小的,这里i-ns少些个ns调试了半天
                {
                    minTime = dist[call][i];
                    ambulance = i;
                }
                else if (dist[call][i] == minTime)
                {
                    if (cars[i - ns] > cars[ambulance - ns]) // 花费时间相同,找有最多车辆的救助站,艹了这里也搞忘加ns了
                        ambulance = i;
                    else if (cars[i - ns] == cars[ambulance - ns] && streets[call][i - ns] < streets[call][ambulance - ns]) // 花费时间也相同,找走的公路条数最少的,妈的这里也没加ns,我是傻逼
                        ambulance = i;
                }
            }
            cars[ambulance - ns]--; // 每次派发都要减去一辆车,这里也要减ns
            int next = ambulance;
            while (true)
            {
                if (next != call)
                {
                    if (next > ns) // 救助站需要加"A-"
                        cout << "A-" << next - ns << " ";
                    else
                        cout << next << " ";
                    next = pre[call][next];
                }
                else
                {
                    cout << next << endl;
                    cout << minTime << endl;
                    break;
                }
            }
        }
    }
    return 0;
}

最后附一个大佬的AC代码,确实是我太菜了,大佬写了这么多种方法,记得给大佬点赞

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值