欢乐赛#61题解(非官方)
2025-11-30 20:08:31
发布于:浙江
以下是这 6 道题的详细解析思路,包括核心问题、关键逻辑、代码逐行解释和边界情况说明,帮助理解每道题的解题思路和代码设计:
- 小明打酱油
核心问题
计算最多能装满的瓶子数,受两个条件限制:① 瓶子总数 n;② 现有酱油 b 能装满的最大瓶子数(需除以单个瓶子容积 a,向下取整)。最终结果取两者的较小值。
关键逻辑
酱油能装满的瓶子数:b // a(整数除法,自动向下取整,比如 16 毫升装 5 毫升 / 瓶,能装 3 瓶);
实际最大可装满数:不能超过瓶子总数 n,因此用 min(n, 酱油能装的瓶数)。
代码解析
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, a, b;
cin >> n >> a >> b;
// 1. 计算酱油最多能装满的瓶数(向下取整)
int max_by_soy = b / a;
// 2. 取“瓶子总数”和“酱油能装瓶数”的最小值,即答案
int result = min(n, max_by_soy);
cout << result << endl;
return 0;
}
边界情况
酱油不够装 1 瓶:如 n=5, a=5, b=3 → 输出 0;
酱油远超瓶子总数:如 n=3, a=2, b=10 → 输出 3;
刚好装满:如 n=4, a=4, b=16 → 输出 4。
- 小明的冬装
核心问题
按 “大衣 → 大衣 + 围巾 → 大衣 + 围巾 + 手套” 的顺序判断是否满足温暖度需求,优先级从高到低,满足则输出对应结果,均不满足则输出 “Too Cold”。
关键逻辑
优先级顺序:单大衣 → 大衣 + 围巾 → 三件套(必须按这个顺序判断,因为单大衣满足时无需考虑组合);
温暖度判断:累计温暖度 ≥ 需求 n 即可。
代码解析
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, a, b, c;
cin >> n >> a >> b >> c;
if (a >= n) { // 单大衣满足
cout << "Coat" << endl;
} else if (a + b >= n) { // 大衣+围巾满足(单大衣不满足时才判断)
cout << "Coat ans scarf" << endl; // 注:样例输出为“ans”,推测是“and”笔误,按题目要求输出即可
} else if (a + b + c >= n) { // 三件套满足(前两者不满足时才判断)
cout << "All" << endl;
} else { // 所有组合都不满足
cout << "Too Cold" << endl;
}
return 0;
}
边界情况
单围巾 / 手套满足但大衣不满足:仍需按规则判断(如 n=5, a=3, b=3 → 输出 “Coat ans scarf”,而非直接用围巾);
三件套刚好等于 n:输出 “All”;
三件套仍不足:输出 “Too Cold”。
3. 地标建筑
核心问题
找出所有满足 “高度 ≥ 其他所有建筑平均高度的 2 倍” 的建筑,按输入顺序输出;无则输出 -1。
关键逻辑
总高度计算:先求所有建筑的总高度 total;
其他建筑的平均高度:对每个建筑 h,其他建筑的总和为 total - h,平均高度为 (total - h)/(n-1)(n≥3,无除零问题);
地标判断:h ≥ 2 * 其他建筑平均高度,满足则加入结果集;
结果输出:有地标则按顺序输出,无则输出 -1。
代码解析(C++不会,用的是Python)
n = int(input())
heights = list(map(int, input().split()))
total = sum(heights)
landmarks = []
for h in heights:
other_sum = total - h # 其他建筑的总高度
other_avg = other_sum / (n - 1) # 其他建筑的平均高度
if h >= 2 * other_avg: # 满足地标条件
landmarks.append(str(h))
if landmarks:
print(' '.join(landmarks)) # 按输入顺序输出地标高度
else:
print('-1') # 无地标
边界情况
多个地标:如样例输入 1(8、9 均满足),按顺序输出;
刚好等于 2 倍平均:视为地标(如 n=3, 高度=[6,2,2] → 其他平均为 2,6≥4 → 输出 6);
所有建筑都不满足:输出 -1。
4. 小明的循环字符串
核心问题
判断字符串 s 能否通过替换星号为小写字母,使其成为若干个长度为 k 的循环节拼接而成(即 s 由 t 个相同的长度为 k 的子串组成,t = len(s)/k)。
关键逻辑
前置检查:字符串长度必须是 k 的整数倍(否则无法拆分出整数个循环节);
循环节位置检查:对于循环节的每个位置 r(0≤r<k),所有 “对应位置” 的字符(即 s[r], s[r+k], s[r+2k], ...)必须一致(星号可替换为任意字符,因此只需非星号字符不冲突);
冲突判断:若同一位置的非星号字符有 2 种及以上,则无法构成循环节。
代码解析
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); // 加速输入
int t;
cin >> t;
while (t--) { // 处理多组测试用例
string s;
int k;
cin >> s >> k;
int n = s.size();
// 1. 前置检查:长度是否为k的整数倍
if (n % k != 0) {
cout << "NO\n";
continue;
}
bool possible = true;
// 2. 检查每个循环节位置r对应的所有字符
for (int r = 0; r < k; ++r) { // r:循环节内的位置(0~k-1)
unordered_set<char> chars; // 存储该位置的非星号字符
for (int i = r; i < n; i += k) { // 遍历所有循环节的第r个位置
if (s[i] != '*') { // 只关注非星号字符
chars.insert(s[i]);
if (chars.size() > 1) { // 出现冲突字符
possible = false;
break;
}
}
}
if (!possible) break; // 冲突则直接退出
}
// 3. 输出结果
cout << (possible ? "YES" : "NO") << '\n';
}
return 0;
}
边界情况
字符串长度为 k(单个循环节):所有星号可自由替换,输出 YES;
同一位置有不同非星号:如 s=abac, k=2 → 位置 0 有 'a' 和 'a'(ok),位置 1 有 'b' 和 'c'(冲突)→ 输出 NO;
全是星号:任意 k(只要长度是 k 的倍数)→ 输出 YES。
5. 小明的群山环线
核心问题
模拟小明在环形山峰上的 m 次移动,每次按当前山峰的木牌数字移动(正负代表方向),最终输出位置。核心是处理环形位置的 “越界循环”。
关键逻辑
环形位置计算:山峰编号是 1-based 环形(1→2→…→n→1),需用模运算处理越界;
移动步骤:
当前位置 curr(1-based)→ 对应数组索引 curr-1(0-based);
移动后位置:curr += a[curr-1](按木牌数字移动);
修正为环形位置:(curr-1) % n(转为 0-based 后取模,处理超界),若结果为负则加 n(处理逆时针移动到负数的情况),最后还原为 1-based。
代码解析
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); // 加速输入
int n, s, m;
cin >> n >> s >> m;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i]; // a[i] 对应第 i+1 座山峰的木牌数字
}
int curr = s; // 初始位置(1-based)
for (int i = 0; i < m; ++i) { // 执行m次移动
curr += a[curr - 1]; // 按当前山峰的木牌移动
curr = (curr - 1) % n; // 转为0-based索引,取模处理环形
if (curr < 0) curr += n; // 处理负数索引(逆时针移动越界)
curr += 1; // 还原为1-based位置
}
cout << curr << endl;
return 0;
}
边界情况
移动步数极大(如 a[i] = 1e9):模运算自动缩减为有效步数,无需担心溢出(建议用 long long 存储 curr 避免极端情况溢出);
逆时针移动到 1 号前:如 n=4, curr=1, a[i]=-1 → curr=0 → (0-1)%4 = -1 → 加 4 得 3 → 还原为 4(正确);
顺时针移动到 n 号后:如 n=4, curr=4, a[i]=2 → curr=6 → (6-1)%4=5%4=1 → 还原为 2(正确)。
6. 小明的数字选取
核心问题
从数组中选最多的数字,使得这些数字的最大公因数(GCD)≠1。核心是找到一个大于 1 的除数 d,统计数组中能被 d 整除的数字个数,最大值即为答案。
关键逻辑
频率统计:由于 a[i] ≤ 1000,先统计每个数字的出现次数(freq[x] 表示 x 出现的次数);
枚举除数 d:遍历所有可能的除数 d≥2(因为 GCD≠1 需至少有一个共同除数 ≥2);
统计可被 d 整除的数字总数:对每个 d,累加所有 d 的倍数(2d、3d、…≤1000)的频率;
取最大值:所有 d 对应的统计数中的最大值,即为最多可选择的数字个数。
代码解析
#include <bits/stdc++.h>
using namespace std;
const int MAX_A = 1000; // a[i] 的最大值
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); // 加速输入
int n;
cin >> n;
vector<int> freq(MAX_A + 1, 0); // 频率数组,freq[x] 是 x 出现的次数
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
freq[x]++;
}
int max_count = 0;
// 枚举所有可能的除数 d≥2
for (int d = 2; d <= MAX_A; ++d) {
int count = 0;
// 累加所有 d 的倍数的频率
for (int multiple = d; multiple <= MAX_A; multiple += d) {
count += freq[multiple];
}
// 更新最大值
if (count > max_count) {
max_count = count;
}
}
cout << max_count << endl;
return 0;
}
边界情况
数组中所有数字都是 1:d≥2 无倍数,max_count=0 → 输出 0;
数组中所有数字有共同除数:如 [2,4,6,8] → d=2 时 count=4 → 输出 4;
多个除数竞争:如样例输入 [2,8,3,6,9] → d=2 对应 2、8、6(count=3),d=3 对应 3、6、9(count=3)→ 输出 3。
全部评论 2
对,连T3AI语言用错都懒得改了是吧
5天前 来自 上海
0神tm全文AI除了标题评论无人工
5天前 来自 上海
0
不理我 :(
2025-11-30 来自 浙江
0


















有帮助,赞一个