官方题解 | 欢乐赛#51 题解
2025-07-10 14:15:21
发布于:广东
官方题解 | 欢乐赛#51 题解
赛纲介绍
本次题目的总体题目难度如下,各位选手可以借此评估一下自身的技术水平
题目编号 题目名称 题目难度
T1 石头剪刀布 入门
T2 小明的购物计划 入门
T3 ac字符串 入门
T4 四舍五入 入门
T5 小明的bingo 入门
T6 3倍 普及-
T1 石头剪刀布
题目大意
输出一个字符使得小明获取胜利。
题解思路
对方出石头,显然我们需要出布,因此输出'C'。
参考代码
#include<bits/stdc++.h>
using namespace std;
int main() {
cout << 'C';
}
T2 小明的购物计划
题目大意
小明去商店购物,不同的结账金额对应了不同的折扣力度,求最终的实际结账金额。
题解思路
使用多分支结构,判断当前的结账金额对应的打折力度,则答案等于结账金额
×
× 折扣。
题目要求保留一位小数输出,因此使用printf进行格式化输出。
参考代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
double ans = 0;
if(n <= 100) ans = n * 0.8;
else if(n <= 300) ans = n * 0.9;
else if(n <= 500) ans = n * 1;
else ans = n * 1.5;
printf("%.1lf", ans);
}
T3 ac字符串
题目大意
对于给定的字符串
s
s, 求其中有多少个子串为 "ac"并输出。
题解思路
由于想要判断的子串长度只有
2
2,因此可以直接遍历整个字符串, 如果
a
[
i
]
a[i] 和
a
[
i
+
1
]
a[i+1] 恰好构成了目标子串"ac",则答案+1。
参考代码
#include<bits/stdc++.h>
using namespace std;
int a[100010], b[100010];
int n;
int main()
{
int cnt = 0 ;
string s;
cin >> s;
for(int i = 0; i < s.size() - 1; i++) {
if(s[i] == 'a' &&s[i + 1] == 'c') cnt++;
}
cout << cnt << endl;
}
T4 四舍五入
题目大意
对于给定的数字
n
n (数位很长,需要使用string来进行读入),求将
n
n 按照四舍五入保留
m
m 位的结果?
题解思路
使用桶数组来存储一下每个密码能够打开的宝箱的数量。 对于每个宝箱, 使得该宝箱的
m
m 个密码能够解开的宝箱数量+1.
将数字保留
m
m 位进行四舍五入,取决于 第
m
+
1
m+1 位,如果第
m
+
1
m+1位大于等于
5
5 , 则第
m
m 位数值加一。
由于在数字
+
1
+1 之后可能会产生进位, 因此需要从后往前维护一下数字的进位, 如果某一位的数字大于
9
9, 则需要设为
0
0 ,并且让上一位
+
1
+1。
参考代码
#include <bits/stdc++.h>
using namespace std;
int n, m;
int main() {
string s;
cin >> n >> s >> m;
if(s[m + 2] >= '5') s[m + 1]++; //第m+1位,下标为m + 2
for(int i = m + 1; i >= 2; i--) {
if(s[i] > '9') {
s[i] = '0';
if(i == 1)s[i - 2] ++; //下标为2时候,上一位要跳过小数点 因此是 s[i - 2]
else s[i - 1]++;
}
}
cout << s.substr(0, m + 2) << endl;
}
T5 小明的bingo
题目大意
给定一个
n
×
n
n×n 的二维数组,对于任何一条长度为
n
n 的直线(包括对角线), 如果直线上数字的总和为一个奇数的话,则可以算是一次 bingo,求bingo的数量。
题解思路
长度为
n
n 的直线一共只有
n
+
2
n+2 条,即
n
n 行,
n
n列, 主对角线, 副对角线。 因此可以按顺序循环遍历
n
n 行,
n
n列, 主对角线, 副对角线,并且计算总和,看本条线上的总和是否是一个奇数,是的话使得答案 +1。
参考代码
#include<bits/stdc++.h>
using namespace std;
int a[5010][5010];
int main(){
int n;
cin >> n;
int cnt = 0;
for(int i =1 ; i <= n; i++)
for(int j = 1; j <= n; j++) cin >> a[i][j];
for(int i = 1; i <= n; i++) { //对于每一行进行判断
int sum = 0;
for(int j = 1; j <= n; j++) sum += a[i][j];
if(sum & 1) cnt++; //总和是奇数则答案+1
}
for(int j = 1; j <= n; j++) { //对于每一列进行判断
int sum = 0;
for(int i = 1; i <= n; i++) sum += a[i][j];
if(sum & 1) cnt++; //总和是奇数则答案+1
}
int sum = 0;
int x = 1, y = 1;
while(x <= n && y <= n) {
sum += a[x][y];
x++;
y++;
} //主对角线
if(sum & 1) cnt++;
sum = 0;
x = 1, y = n;
while(x <= n){
sum += a[x][y];
x++;
y--;
} //副对角线
if(sum & 1) cnt++;
cout << cnt << endl;
}
T6 3倍
题目大意
给定一个长度是
n
n 的数组, 对于其中所有的差值为
3
3 的倍数的数对
a
i
,
a
j
(
1
≤
i
,
j
≤
n
)
a
i
,a
j
(1≤i,j≤n), 求其最大的差值并且输出.
题解思路
如果直接枚举所有的数对
(
i
,
j
)
(i,j) ,则复杂度为
O
(
n
2
)
O(n
2
),
n
n的上界为
100000
100000,显然超时。
考虑到如果两个数字
a
i
,
a
j
a
i
,a
j
的差值为
3
3, 则
a
i
%
3
=
a
j
%
3
a
i
%3==a
j
%3。
因此可以将所有数字对
3
3 取模, 对于余数是
0
,
1
,
2
0,1,2 三种情况分别求最大值和最小值。
最后对三个情况分别使用最大值减去最小值获取对应的最大差值, 在三种结果中取最大即可。
参考代码
#include <bits/stdc++.h>
using namespace std;
int inf = 1e9;
int mi[5]= {10000, 10000, 10000}, ma[5];
int n[1000010];
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
int x;
cin >> x;
mi[x % 3] = min(mi[x % 3], x);
ma[x % 3] = max(ma[x % 3], x); //维护最大值和最小值
}
int ans = 0;
for(int i = 0; i < 3; i++) ans = max(ans, ma[i] - mi[i]);
cout << ans << endl;
}
这里空空如也
有帮助,赞一个