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.
10
观察这两个数字从前到后第一个不相同的数字,由于9>1,因此9>10。
用同样的方法,我们可以很容易地证明1919>114514:
1919..
114514
或者是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;
}