Advertisement

2020年中南大学研究生招生夏令营机试题

阅读量:

2020年中南大学研究生招生夏令营机试题

题目链接

A题

题目描述

众所周知,彩虹有7种颜色,我们给定七个 字母和颜色 的映射,如下所示:
‘A’ -> “red”
‘B’ -> “orange”
‘C’ -> “yellow”
‘D’ -> “green”
‘E’ -> “cyan”
‘F’ -> “blue”
‘G’ -> “purple”
但是在某一天,彩虹的颜色少了几种,你能告诉PIPI哪些彩虹的颜色没有出现过吗?

输入

复制代码
    
    

输入包含多组测试用例。
对于每组测试用例,输入n个合法的颜色字符串(0<=n<=100),输出有多少种颜色没有出现过,并分别输出对应的字母。

输出

对于每一组测试样例,输出一个数字,代表缺失的颜色种数,然后按照升序输出缺失颜色对应的字母。

样例输入

复制代码
    3
    red
    orange
    cyan
    
    

样例输出

复制代码
    4 
    C
    D
    F
    G
    
    

题目思路

这题就是道签到题,直接暴力解决,用数组把七种颜色存储起来。每次输入颜色都与7种颜色相比,是否已经输入过此种颜色,如果没有则进行标记。同时记录已经输入了多少种颜色

上代码

复制代码
    #include<cstdio>
    #include<cstring>
    int main()
    {
    int n, cnt;
    char s[10][10] = {"red", "orange", "yellow", "green", "cyan", "blue", "purple"};
    int flag[7];
    char s1[10];
    while(~scanf("%d", &n))
    {
        cnt = 7;
        memset(flag, 0, sizeof(flag));
        for(int i = 0; i < n; i++)
        {
            scanf("%s", s1);
            for(int j = 0; j < 7; j++)
            {
                if(flag[j])    continue;
                if(!strcmp(s1, s[j]))
                {
                    flag[j] = 1;
                    cnt--;
                    break;
                }
            }
        }
        printf("%d\n", cnt);
        for(int i = 0; i < 7; i++)
        {
            if(flag[i]) continue;
            printf("%c\n", 'A'+i);
        }
    }
    return 0;
    }
    
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-15/OU14VwoCMWriD2JFacASK6klBZLN.png)

B题

题目链接

题目描述

给定 n 个整数对(ai, bi) , 每个整数对的价值是(i-1)*ai + (n-i)*bi (下标从1开始, 这里的 ai 、bi 和输入不一定对应),然后问所有整数对的最小价值总和。

输入

输入包含多组测试用例。
对于每组测试用例,首先输入数对的数量n(n<=1e5)
接下来输入n对数对 ai bi (0<=ai,bi<=1e9)

输出

对于每组测试用例,输出这些整数对的最小价值总和。

样例输入

复制代码
    3
    3 2
    2 4
    6 1
    
    

样例输出

复制代码
    11
    
    

提示

0 * 6 + 2 * 1 + 1 * 3 + 1 * 2 + 2 * 2 + 0 * 4 = 11

题目思路

任取两个位置的对数P1,P2。(假设P1的位置为i在P2的位置j前面)(i < j)

则价值和为

value1 = (i - 1) * P1.a+ (n - i) * P1.b + (j - 1) * P2.a + (n - j) * P2.b

将P1和P2的位置对换一下

则价值和为

value2 = (i - 1) * P2.a+ (n - i) * P2.b + (j - 1) * P1.a + (n - j) * P1.b

value1 - value2 = (j - i) * ( (a2 - b2) - (a1 - b1) )

当a2 - b2 < a1 - b1时,value1 - value2 < 0

说明P1在i位置P2在j位置的价值和比P2在i位置P1在j位置的价值和小,不需要更换位置

通过上面的式子可以看出a-b大的放在前面,只需要用一个sort排序一下就可以了

上代码

复制代码
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef struct dot
    {
    ll a;
    ll b;
    }dot;
    dot p[100005];
    int cmp(const dot &p1, const dot& p2)
    {
    return (p1.a - p1.b) > (p2.a - p2.b);
    }
    int main()
    {
    int n;
    ll ans;
    while(~scanf("%d", &n))
    {
        for(int i = 0; i < n; i++)
            scanf("%lld %lld", &p[i].a, &p[i].b);
        sort(p, p+n, cmp);
        ans = 0;
        for(int i = 0; i < n; i++)
            ans += i * p[i].a + (n - i -1) * p[i].b;
        printf("%lld\n", ans);
    }
    return 0;
    }
    
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-15/bBAt3Ej2pimL4lUTqnZMCN5wfKsh.png)

C题

题目链接

题目描述

PIPI每天早上都要从CSU的某个位置走到另一个位置。CSU可以抽象为一个n*m的方格。PIPI每天都要从(x1,y1)走到(x2,y2),规定每次可以向下或者向右移动一格。总共有q次询问,每次询问从(x1,y1)走到(x2,y2)有多少条不同的路径,答案对1000000007取模。

输入

输入包含多组测试用例。
对于每组测试用例,首先输入三个整数n,m,q(1<=n,m,q<=5000),代表方格的大小和询问次数。
接下来q行,每行输入四个正整数 x1, y1 ,x2,y2(1<=x1<=x2<=n ,1<=y1<=y2<=m) 。意义如题所示。

输出

4 4 4
1 1 1 1
1 1 2 2
1 1 1 2
1 1 2 1

样例输入

复制代码
    1
    2
    1
    1
    
    

题目思路

这题思路非常简单就是一个高中数学排列组合,从一个点(x1, y1)走到另外一个点(x2, y2)有多少条路径。

a = x2 - x1

b = y2 - y1

t = a + b

答案就为C_t^a

总共走t步,其中选a步向左走,其余的步数向下走。

问题在于数据太大会溢出要取模问题

(a*b)%mod = (a%mod * b%mod)%mod

但是没有

(a/b)%mod = (a%mod / b%mod )%mod

所以需要将除转化为逆元。在此处不讲述逆元的知识

inv(a) 表示为a的逆元

(a /b)%mod = (a * inv(b)) %mod

上代码

复制代码
    #include<cstdio>
    #include<vector>
    typedef long long ll;
    using namespace std;
    const ll mod = 1000000007;
    ll p1[5005];
    ll quick_pow(ll a, ll b)
    {
    ll ans = 1;
    while(b)
    {
        if(b&1)
            ans = ans * a % mod;
        a = a * a % mod;
        b>>=1;
    }
    return ans;
    }
    int main()
    {
    
    int n, m, p, x1, x2, y1, y2, a, b, tem1, tem2;
    ll ans;
    for(int i = 1; i <= 5000; i++)
        p1[i] = quick_pow(i, mod-2);
    while(~scanf("%d %d %d", &n, &m, &p))
    {
        for(int i = 0; i < p; i++)
        {
            ans = 1;
            scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
            a = x2 - x1 + y2 - y1;
            if(x2 - x1 < y2 - y1)
                b = x2 -x1;
            else
                b = y2 - y1;
            tem1 = a;
            tem2 = b;
            for(int j = 0; j < b; j++)
            {
                ans = ans * tem1 % mod;
                ans = ans * p1[tem2] % mod;
                tem1--;
                tem2--;
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
    }
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-15/AJwSyYo5gDKcj4UrQtdHuFfP9Tx3.png)

D题

题目链接

题目描述

有 m 根木棍,m = n * k,n 个桶,每个桶由 k 块木板构成,桶的容量由最短的木板长度决定,桶的底面积为 1,现要求任意两个桶间的容量差小于等于 L,问 n 个桶的最大容量和。
如果无法满足组成n个桶,输出0.

输入

第一行输入三个整数 n,k, L(n _k <=1e5)。
第二行输入n_k根木板长度,a1,a2,a3…1 ≤ a**i ≤ 10^9

输出

输出n个木桶最大容量和。

样例输入

复制代码
    4 2 1
    2 2 1 2 3 2 2 3
    
    

样例输出

复制代码
    7
    
    

提示

这四个桶可以是1 2, 2 2, 2 3, 2 3,那么答案就是1+2+2+2 = 7。

题目思路

先把木板从小到大排好序。如果要组成n个符合要求的桶子。则排好序后第n块木板的长度小于等于第一块木板的长度 + L。求出比第一块木板长度长L的总共有K块。如果K<n说明不可能组成n的符合要求的桶子,直接输出0。(长度小的木板能组成一个木桶,总容量才会大)

复制代码
    下面为找出的K个符合要求的n个木桶的最短木板(长度从小到大排序)
    A(1) A(2) A(3) ... A(k)
    先把A(1)作为第一个木桶的最短木板,因为要尽可能多的短木板组成一个木桶。又要有n个符合要求的最短木板,
    所以挑选a = min(k-1, K-n)块长度小的木板和A(1)组成一个木桶。
    再挑选A(1+min(K-1, K-n)+1)作为第二个木桶的最小木板,再挑选min(k-1, K-n-a)块长度小的木板和其组成木桶
    一直挑选下去即可
    
    

上代码

复制代码
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    ll board[100005];
    int main()
    {
    int n, k, l, i, j, cnt;
    ll ans;
    while(~scanf("%d %d %d", &n, &k, &l))
    {
        for(int i = 0; i < n*k; i++)
        scanf("%lld", &board[i]);
        sort(board, board+n*k);
        if(board[n-1] - board[0] > l)
            printf("0\n");
        else
        {
            j = cnt = ans = 0;
            for(i = n-1; i < n*k; i++)
            {
                if(board[i] - board[0] <= l)
                    continue;
                else
                    break;
            }
            i = i - n; 
            while(i > 0)
            {
                if(i >= k-1)
                {
                    ans += board[j];
                    i -= k-1;
                    j += k;
                    cnt++;
                }
                else
                {
                    ans += board[j];
                    j += i+1;
                    i = 0;
                    cnt++;
                }
            }
            if(cnt < n)
            {
                for(i = j; i < n*k; i++)
                {
                    if(cnt >= n)
                        break;
                    ans += board[i];
                    cnt++;
    
                }
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
    }
    
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-15/ZIpdnygwQ4U9M2iBJkqC16j5GzEO.png)

全部评论 (0)

还没有任何评论哟~