【2022 NEUQ-ACM-招新赛】

7-1 Win

为了实现建设世界一流大学和建设世界一流学科的目标,不少大学都用各种方式提升排名:发表论文、 申请基金、提升多样性. . . 不过看起来这些并不容易,而且 US News 和 Times 这样的机构并不一定会 公正评判你的工作。因此,一些大学更聪明——自己发布排行榜,这可以使得自己的名次间接变好。比如,通过上海某大学发布的软科排名(ARWU)作为桥梁,咖波甚至可以论证他的小汤河职业技术学院要好于清华大学:

现在,给定三个大写字母,你需要判断:

如果这三个大写字母分别为:NEU,则输出:Win

如果这三个大写字母分别为:THU,则输出:Lose

否则输出:?

输入格式:

一行三个大写字母,如题意所示

输出格式:

一行一个字符串,如题意所示

输入样例1:

NEU

输出样例1:

Win

输入样例2:

THU

输出样例2:

Lose

输入样例3:

KFC

输出样例3:

?

思路:if判断一下即可

C++代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin >> s;
    if(s == "NEU") cout << "Win";
    else if(s == "THU") cout << "Lose";
    else cout << "?";
    return 0;
}

7-2 比大小

知名数学家田所浩二先生证明了:

9>10

证明:写下两个数的十进制表示:

9​.

1​0

观察这两个数字从前到后第一个不相同的数字,由于9>1,因此9>10。

用同样的方法,我们可以很容易地证明1919>114514:

19​19..

11​4514

或者是999>99:

99.​

999​

现在,请你给田所浩二先生写一个程序,用来比较两个输入的数字。

输入格式:

第一行一个整数T(1≤T≤106) ,表示有T组数据

接下来T行,每行两个整数a,b(1≤a,b≤109)

输出格式:

输出总共T行,对于第i行:

如果"a>b",则输出:>

如果"a=b",则输出:=

如果"a<b",则输出:<

输入样例:

5
9 10
114514 1919
999 99
131 131
1314 520

输出样例:

>
<
>
=
<

提示:

为避免输出超时,请使用cout << "\n"替代cout << endl

思路:在短的数字后补零使两字符长度相等,再根据题目要求逐字符比较

C++代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin >> n;
    for(int i = 0; i < n; i++){
        string a, b;
        cin >> a >> b;
        int len = max(a.length(), b.length());
        for(int j = 0; j <= len; j++){
            if(a[j] > b[j] || (a[j] != '\0' && b[j] == '\0')){
                cout << ">" << endl;
                break;
            }else if(a[j] < b[j] || (b[j] != '\0' && a[j] == '\0')){
                cout << "<" << endl;
                break;
            }else if(a[j] == '\0' && b[j] == '\0'){
                cout << "=" << endl;
                break;
            }
        }
    }
    return 0;
}

7-3 矩阵乘法

Alice在学线性代数。她觉得线代的计算特别麻烦,于是就来找你,希望你可以给她写一个程序计算两个矩阵的乘积。

矩阵乘法介绍:
矩阵A是一个N行P列的矩阵。
矩阵B是一个K行M列的矩阵。
当P=K时,A和B可以相乘(仅限于AB, BA不一定可行)
假设矩阵C=AB,那么Ci,j​=∑t=1P(或K)​Ai,t​∗Bt,j​

举个例子,假设A是一个2×3的矩阵,B是一个3×2的矩阵,最终结果C是一个2×2的矩阵,如下图所示

输入格式:

输入共一行,有三个整数N,P,M(N,P,M≤100)。表示矩阵A是一个N×P的矩阵,矩阵B是一个P×M的矩阵。

接下来N行,每行P个整数,读入矩阵A。

再接下来P行,每行M个整数,读入矩阵B。

数据保证在输入输出数据可以用int类型存储。

输出格式:

输出N行M列的矩阵C。每行最后一个数后面有一个空格。

输入样例:

在这里给出一组输入。例如:

3 3 3
1 3 2
1 0 0
1 2 2
0 0 2
7 5 0
2 1 1

输出样例:

在这里给出相应的输出。例如:

25 17 4 
0 0 2 
18 12 4 

思路:按照矩阵乘法规则计算 

C++代码

#include <bits/stdc++.h>
using namespace std;
int main(){
    int n, p, m;
    cin >> n >> p >> m;
    int a[n + 1][p + 1], b[p + 1][m + 1];
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= p; j++){
            cin >> a[i][j];
        }
    }
    for(int i = 1; i <= p; i++){
        for(int j = 1; j <= m; j++){
            cin >> b[i][j];
        }
    }
    long int c[105][105], temp = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
          for(int k = 1; k <= p; k++){
            temp += a[i][k] * b[k][j];
          }
          c[i][j] = temp;
          temp = 0;
        }

    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            cout << c[i][j] << " ";
        }
        cout << "\n";
    }
    return 0;
}

7-4 疯狂星期四

已知2022年10月11日是星期二

现在给定你一个日期,你需要计算当天是星期几。

输入格式:

一行三个整数M,D,Y,表示所求日期为:M月D日,Y年

1600≤Y≤2400,保证输入日期均为合法日期。

输出格式:

输出一个数字,表示当前是星期几。

如果星期天,则输出0。

输入样例1:

8 17 1926

输出样例1:

2

输入样例2:

2 29 1904

输出样例2:

1

思路:将当前日期与给定日期转换为自0001年01月01日以来经过的天数,两者相减得到两日期间隔的天数,由此计算给定日期是星期几

C++代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
    long long time = 0;
    int m, d, y;
    cin >> m >> d >> y;
    time += d;
    if(m == 2 && d == 29) time--;
    for(int i = 1; i < m; i++){
        switch(i){
            case 1: time += 31; break;
            case 2: time += 28; break;
            case 3: time += 31; break;
            case 4: time += 30; break;
            case 5: time += 31; break;
            case 6: time += 30; break;
            case 7: time += 31; break;
            case 8: time += 31; break;
            case 9: time += 30; break;
            case 10: time += 31; break;
            case 11: time += 30; break;
        }
    }
    time += y * 365 + y / 4 + y / 400 - y / 100;
    m = 10; d = 11; y = 2022;
    long long now = 0;
    now += d;
    for(int i = 1; i < m; i++){
        switch(i){
            case 1:  now+= 31; break;
            case 2: now += 28; break;
            case 3: now += 31; break;
            case 4: now += 30; break;
            case 5: now += 31; break;
            case 6: now += 30; break;
            case 7: now += 31; break;
            case 8: now += 31; break;
            case 9: now += 30; break;
            case 10:now+= 31; break;
            case 11:now += 30; break;
        }
    }
    now += y * 365 + y / 4 + y / 400 - y / 100;
    long long gap = fabs(now - time);
    int ans;
    if(now >= time){
        ans = 2 - (gap % 7) + 7; 
    }else{
        ans = (2 + (gap % 7)) % 7;
    }
    if(ans == 7) cout << 0;
    else if(ans > 7) cout << ans - 7;
    else cout << ans;
    return 0;
}


7-5 排列

给你一个长度为n的排列p1​,p2​,p3​,...,pn​(1≤pi​≤n,且对于任意i=j,都有pi​=pj​)

再给你一个整数k,每次操作的定义如下:

选定一个下标j(1≤j≤n−k+1),记m=max{pj​,pj+1​,...,pj+k−1​},然后令pj​,pj+1​,...,pj+k−1​的值都等于m。

你需要使用最少的操作次数,使得p中所有元素的值都等于n。

输入格式:

第一行两个整数n,k (2≤n≤106,2≤k≤n)

接下来一行n个整数,用空格隔开,分别表示p1​,p2​,...,pn​

输出格式:

一行一个整数,表示最小的操作次数。

输入样例:

6 3
1 6 4 2 3 5

输出样例:

3

样例解释:

第一次操作选择:j=1,操作后p为:6 6 6 2 3 5

第二次操作选择:j=3,操作后p为:6 6 6 6 6 5

第三次操作选择:j=4,操作后p为:6 6 6 6 6 6

思路:由题目要求可知,若想要以最少的操作次数将p中所有元素转化为n,则一定要从排列中最大的数n开始操作,将包括这个数周围的k个数转化为n。因此,每次操作都转化了k - 1个数,而一共有n - 1个数需要转化,因此最少的转化次数即为(n - 1/ k - 1)向上取整的值

C++代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int n, k;
    cin >> n >> k;
    int ans = (n - 1) / (k - 1);
    if((n - 1) % (k - 1)) cout << ans + 1;
    else cout << ans;
    return 0;
}

7-6 小步点

现在是跑步时间。

咖波需要依次经过地图上的五个点位才能完成任务,为了节省体力,他希望以最短的距离跑完这五个点位。

现在给出这五个点位的坐标,你需要帮咖波求出最短距离。(咖波可以从任意一个坐标开始跑步)

输入格式:

总共五行

第i行有两个整数xi​,yi​(−103≤xi​,yi​≤103),表示第i个点位的坐标值。

数据保证不存在坐标相同的点。

输出格式:

输出一个实数,表示最短的跑步距离(保留三位小数)

输入样例:

0 0
0 2
2 2
2 0
1 1

输出样例:

6.828

样例解释:

可选择从(0,0)点开始,依次经过(0,2),(1,1),(2,0),(2,2)

此时距离为:2+√2​+√2​+2=6.828,可以证明这是最短的路径。

思路:因为不会DFS和BFS,而且题目只有五个点,所以就直接用5个for循环遍历吧

C++代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int a[5][2], b[5];
    double ans = 114514;
    memset(b, 0, sizeof(b));
    for(int i = 0; i < 5; i++){
        cin >> a[i][0] >> a[i][1];
    }
    for(int i = 0; i < 5; i++){
        b[i] = 1;
        double temp = 0;
        for(int j = 0; j < 5; j++){
            if(b[j] == 1) continue;
            b[j] = 1;
            temp += sqrt((a[j][0] - a[i][0]) * (a[j][0] - a[i][0]) + (a[j][1] - a[i][1]) * (a[j][1] - a[i][1]));
            for(int m = 0; m < 5; m++){
                if(b[m] == 1) continue;
                b[m] = 1;
                temp += sqrt((a[m][0] - a[j][0]) * (a[m][0] - a[j][0]) + (a[m][1] - a[j][1]) * (a[m][1] - a[j][1]));
                for(int n = 0; n < 5; n++){
                    if(b[n] == 1) continue;
                    b[n] = 1;
                    temp += sqrt((a[n][0] - a[m][0]) * (a[n][0] - a[m][0]) + (a[n][1] - a[m][1]) * (a[n][1] - a[m][1]));
                    for(int k = 0; k < 5; k++){
                        if(b[k] == 1) continue;
                        temp += sqrt((a[k][0] - a[n][0]) * (a[k][0] - a[n][0]) + (a[k][1] - a[n][1]) * (a[k][1] - a[n][1]));
                        if(temp < ans) ans = temp;
                        temp -= sqrt((a[k][0] - a[n][0]) * (a[k][0] - a[n][0]) + (a[k][1] - a[n][1]) * (a[k][1] - a[n][1]));
                    }
                    b[n] = 0;
                    temp -= sqrt((a[n][0] - a[m][0]) * (a[n][0] - a[m][0]) + (a[n][1] - a[m][1]) * (a[n][1] - a[m][1]));
                }
                b[m] = 0;
                temp -= sqrt((a[m][0] - a[j][0]) * (a[m][0] - a[j][0]) + (a[m][1] - a[j][1]) * (a[m][1] - a[j][1]));
            }
            b[j] = 0;
            temp -= sqrt((a[j][0] - a[i][0]) * (a[j][0] - a[i][0]) + (a[j][1] - a[i][1]) * (a[j][1] - a[i][1]));
        }
        b[i] = 0;
    }
    cout << fixed << setprecision(3) << ans;
    return 0;
}

7-7 原神生日会

注:空、荧、派蒙均为游戏原神里的人名。

有a个空(男旅行者)和b个荧(女旅行者)在会场外排队参加原神生日会。不幸的是,会场里只有N个座位,而且已经有若干个派蒙(可以是0个)已经坐在会场里面了。

  • 每个男旅行者都希望坐在他边上的是女旅行者或者派蒙。
  • 每个女旅行者都希望坐在她边上的是男旅行者或者派蒙。

换句话说,男旅行者不希望和其他男旅行者坐一起,女旅行者不希望和其他女旅行者坐一起。

如果会场内没有符合旅行者心意的位置,那么旅行者会选择不参加原神生日会。

作为活动组织者的你,希望能参加生日会的旅行者尽可能的多,现在给出会场内每个派蒙的位置,请你求出最多有几个旅行者会来参加生日会。

输入格式:

输入共两行。
第一行有三数,分别为N,a,b(1≤n≤2∗105,0≤a,b≤2∗105,a+b>0)。表示会场内有N个位子,会场外有a个男旅行者,有b个女旅行者。

第二行是一个由字符"."和字符"P"组成的字符串。

"."表示空位,"P"表示这个位置被派蒙占了。

输出格式:

输出一个整数,表示最多可以有几个旅行者参加生日会。

输入样例:

在这里给出一组输入。例如:

11 3 10
.P....PP.P.

输出样例:

在这里给出相应的输出。例如:

7

样例解释

我们用P来表示派蒙,A来表示男旅行者,B来表示女旅行者,最终会场内的座位情况是这样的:BPABABPPAPB

思路:由题目要求可知,每个派蒙间的座位数如果是偶数n,则男和女旅行者均能得到n/ 2个座位;如果派蒙间的座位数为奇数,则男和女旅行者均能得到(n - 1) / 2个座位,同时会出现一个可以自由分配给男或女旅行者的空位。因此,可先将空位分配给男旅行者,再将空位一个一个多分给女旅行者,其中得到的最大的参加人数即为答案

C++代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int N, a, b, len = 0, t1 = 0, t2 = 0, ans;
    string s;
    cin >> N >> a >> b >> s;
    for(int i = 0; i < N; i++){
        if(s[i] == '.') len++;
        if(s[i] == 'P' || i == s.length() - 1){
            int k = (len + 1) / 2;
            t1 += k;
            t2 += len - k;
            len = 0;
        }
    }
    ans = max(min(t1, a) + min(t2, b), min(t1, b) + min(t2, a));
    cout << ans;          
    return 0;
}

7-8 漏字文

有意避免使用某个或某几个特定字母的写成的文章称漏字文(英语lipogram,希腊语lipagrammatos,意为“失踪的字母”),漏字文可能在写作或文字游戏中出现。公元前5世纪希腊诗人里斐奥多鲁斯(Tryphiodorus)写的24卷史诗中,每一卷都省略希腊字母中的一个不同字母。

现在给你一段仅由空格和小写字母组成的字符串,请你找出其中最长的一段连续的漏字文,并输出漏字文的长度(即该段文字中字母的个数)。

输入格式:

输入共两行。
第一行一个数N(1≤N≤105),表示有N个由小写字母组成的单词。
第二行是一个字符串,有N个长度不超过10的单词,每个单词间用一个空格隔开。

输出格式:

一个整数,表示漏字文的长度。

输入样例:

在这里给出一组输入。例如:

9
the quick brown fox jumps over the lazy dog

输出样例:

在这里给出相应的输出。例如:

32

样例解释

“the quick brown fox jumps over the lazy dog”包含了所有的字母。
其中最长的漏字文是“the quick brown fox jumps over the lazy”,长度是32(即里面有32个字母)。这段文字没有字母d和g,符合漏字文的条件。

注:漏字文必须是连续的一段

思路:从第一个单词开始将单词加入漏字文句子中,当加入了某个单词后句子不再是漏字文时,就删除此句子中最前面的单词,直到句子再次变成漏字文。在此过程中寻找最长的漏字文句子即可

C++代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int n, num[26], cnt = 0, ans = -1, temp = 0;
    memset(num, 0, sizeof(num));
    cin >> n;
    queue<string> vec;
    for(int i = 0; i < n; i++){
        string s;
        cin >> s;
        vec.push(s);
        temp += s.length();
        for(int j = 0; j < s.length(); j++){
            if(num[s[j] - 'a'] == 0) cnt++;
            num[s[j] - 'a']++;
        }
        if(cnt == 26){
            while(cnt >= 26){
                string t = vec.front();
                vec.pop();
                temp -= t.length();
                for(int j = 0; j < t.length(); j++){
                    num[t[j] - 'a']--;
                    if(num[t[j] - 'a'] == 0) cnt--;
                }
            }
        } 
        ans = max(ans, temp);
    }
    cout << ans;
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值