CCC 2025 Junior 题解
问题J1:过山车之旅
问题描述
你正在CEMC游乐园游玩。游乐园里的一项游乐设施是过山车,它有一列火车,火车上有若干节车厢,每节车厢乘坐的人数相同。
当你到达过山车处时,你看到了一条排队的队伍。假设每趟过山车的每节车厢都坐满,你的任务是判断你是否能登上下一趟过山车。
输入规范
输入的第一行包含一个正整数N
,表示你在队伍中的位置。例如,如果N
为5,那么你就是队伍中的第5个人。
输入的第二行包含一个正整数C
,表示火车的车厢数量。
输入的第三行包含一个正整数P
,表示每节车厢能乘坐的人数。
输出规范
输出yes
或no
,表明你是否能登上下一趟过山车。
样例输入1
14
3
2
样例输出1
no
样例输出1解释
火车有3节车厢,每节车厢能坐2人。因此,下一趟过山车可以乘坐6人。由于你是队伍中的第14个人,所以你不能登上下一趟过山车。
样例输入2
12
4
3
样例输出2
yes
样例输出2解释
火车有4节车厢,每节车厢能坐3人。因此,下一趟过山车可以乘坐12人。由于你是队伍中的第12个人,所以你能登上下一趟过山车。
问题J2:甜甜圈店
问题描述
一家甜甜圈店的店主一整天都在烘焙和售卖甜甜圈。
根据一天中发生的事件,你的任务是确定店铺关门时剩余的甜甜圈数量。
输入规范
输入的第一行包含一个非负整数D
,表示店铺刚开门时可供售卖的甜甜圈数量。
输入的第二行包含一个正整数E
,表示一天中发生的事件数量。接下来的E
对输入行描述了这些事件。
每对输入行中的第一行包含+
(加号),表示烘焙了甜甜圈;或者包含-
(减号),表示卖出了甜甜圈。每对输入行中的第二行包含一个正整数Q
,表示与该事件相关的甜甜圈数量。
对于每次甜甜圈的销售,正整数Q
的值都小于或等于当时可供售卖的甜甜圈数量。
输出规范
输出一个非负整数R
,即店铺关门时剩余的甜甜圈数量。
样例输入
10
3
+
24
-
6
-
12
样例输出
16
样例输出解释
店铺开门时有10个甜甜圈,当天发生了3个事件。店主首先烘焙了24个甜甜圈,然后卖出了6个,接着又卖出了12个。剩余的甜甜圈数量为10 + 24 - 6 - 12 = 16
。
问题J3:产品代码
问题描述
一家商店雇佣了代码清理团队来帮助更新所有产品代码。
原始产品代码是由字母、正整数和负整数组成的序列。例如,cG23mH-9s
是一个产品代码,它包含两个大写字母、三个小写字母、一个正整数和一个负整数。
新的产品代码是通过删除所有小写字母,按顺序保留所有大写字母,并将所有整数相加形成一个新整数,放在代码末尾得到的。例如,cG23mH-9s
的新代码是GH14
。
你的任务是根据原始产品代码列表确定新的产品代码。
输入规范
输入的第一行包含一个正整数N
,表示需要更新的原始产品代码数量。接下来的N
行每行包含一个原始产品代码。
每个原始产品代码至少包含一个大写字母、一个小写字母和一个整数。并且,一个正整数不会紧跟在另一个整数后面。这意味着,例如,23
表示整数23,而不是整数2后面跟着整数3。
以下表格展示了15分的分配情况:
分数 | 描述 |
---|---|
2分 | 所有整数都是正的且为一位数。 |
2分 | 所有整数都是一位数。 |
7分 | 任何正整数都可能是多位数。 |
4分 | 任何整数都可能是多位数。 |
输出规范
输出N
个新的产品代码,每行一个。
样例输入1
1
AbC3c2Cd9
样例输出1
ACC14
样例输出1解释
对于这个原始产品代码,按顺序保留大写字母A、C和C,整数的和为3 + 2 + 9 = 14
。
样例输入2
3
Ahkiy-6ebvXCV1
393hhhUHkbs5gh6QpS-9-8
PL12N-2G1234Duytrty8-86tyaYySsDdEe
样例输出2
AXCV-5
UHQS387
PLNGDYSDE1166
样例输出2解释
对于第一个原始产品代码,按顺序保留大写字母A、X、C和V,整数的和为-6 + 1 = -5
。
对于第二个和第三个原始产品代码,同样按顺序保留大写字母,整数的和分别为393 + 5 + 6 - 9 - 8 = 387
和12 - 2 + 1234 + 8 - 86 = 1166
。
问题J4:晴天
问题描述
CEMCity有大量的历史天气数据。数据中的每一天都被记录为晴天或降水天。杰里米想找出连续晴天的最长记录。不幸的是,数据中恰好有一天是错误的,但杰里米不知道是哪一天。
你的任务是帮助杰里米确定可能的连续晴天的最大天数。
输入规范
输入的第一行包含一个正整数N
,表示历史数据中的天数。接下来的N
行每行包含字符S
或P
,分别按时间顺序表示晴天或降水天。
以下表格展示了15分的分配情况:
分数 | 描述 | 范围 |
---|---|---|
2分 | 历史数据中的天数不多。数据由一整块S (代表晴天)后面跟着一整块P (代表降水天)组成。其中一个块可能为空。 |
N ≤ 1000 |
4分 | 历史数据中的天数不多。数据中包含S 和P ,顺序可能是混合的。 |
N ≤ 1000 |
9分 | 历史数据中的天数可能很多。 | N ≤ 500000 |
输出规范
输出一个非负整数M
,即可能的连续晴天的最大天数。
样例输入
8
P
S
P
S
S
P
P
S
样例输出
4
样例输出解释
如果第三天的数据是错误的,那么从第二天到第五天都是晴天,即有四个连续的晴天。这是可能的连续晴天的最大天数。也就是说,无论哪一天的数据是错误的,都不会有五个(或更多)连续的晴天。
问题J5:连接区域
问题描述
艾娃正在一个方格网格上玩策略游戏。每个方格都有一个相关的成本。当从左到右读取方格的成本时,从第一行开始,会呈现出前M
个正整数按升序排列的重复模式:1,2,3, ..., M, 1,2,3, ..., M, 1,2,3, ...
。在这个模式中,M
代表一个方格的最大成本。在所示的方格网格中,M
等于5。
艾娃需要在每一行购买一个方格,以创建一条从上方区域(第一行方格上方)到下方区域(最后一行方格下方)的连接路径。购买的第一个方格必须在第一行。随后购买的每个方格必须与之前购买的方格共享一条边或一个角。在所示的方格网格中,艾娃的连接路径成本为9。
给定一个方格网格,你的任务是确定连接上下区域的路径的最小成本。
输入规范
输入的第一行包含一个正整数R
,表示网格的行数。
输入的第二行包含一个正整数C
,表示网格的列数。
输入的第三行包含一个正整数M
,其中M ≤ 100000
,代表一个方格的最大成本。
以下表格展示了15分的分配情况:
分数 | 描述 | 范围 |
---|---|---|
3分 | 有两行,最多十列。 | R = 2 且C ≤ 10 |
8分 | 最多十行,最多十列。 | R ≤ 10 且C ≤ 10 |
2分 | 最多100行,最多100列。 | R ≤ 100 且C ≤ 100 |
2分 | 网格可能非常大。 | R ≤ 20000 且C ≤ 20000 |
输出规范
输出一个正整数P
,即连接上下区域的路径的最小成本。
样例输入
3
5
7
样例输出
6
样例输出解释
每个方格的成本已显示。为了最小化连接路径的成本,艾娃应该购买的方格序列以绿色突出显示。
以下是针对CCC Junior组一至五题的题解,包括思路讲解和对应的C++代码实现:
题目 J1: Roller Coaster Ride
思路讲解:
本题要求判断给定位置的人是否能在下一班过山车上。我们需要计算火车的总承载人数,即火车的车厢数乘以每节车厢的承载人数。如果当前位置的人数小于或等于总承载人数,则可以上车,输出 "yes";否则输出 "no"。
C++代码:
#include <iostream>
using namespace std;
int main() {
int N, C, P;
cin >> N >> C >> P;
if (N <= C * P) {
cout << "yes" << endl;
} else {
cout << "no" << endl;
}
return 0;
}
题目 J2: Donut Shop
思路讲解:
本题要求计算一天结束时剩余的甜甜圈数量。我们需要初始化一个变量来存储剩余的甜甜圈数量,然后根据每个事件更新这个数量。如果事件是添加('+'),则增加相应的数量;如果事件是出售('-'),则减少相应的数量,但要确保剩余数量不小于0。
C++代码:
#include <iostream>
using namespace std;
int main() {
int D, E, Q;
cin >> D >> E;
for (int i = 0; i < E; ++i) {
char event;
cin >> event >> Q;
if (event == '+') {
D += Q;
} else {
D -= Q;
if (D < 0) D = 0;
}
}
cout << D << endl;
return 0;
}
题目 J3: Product Codes
思路讲解:
本题要求将原始产品代码转换为新格式。新格式要求移除所有小写字母,保留大写字母的顺序,并将所有整数相加。我们可以通过遍历原始代码,识别大写字母和整数,然后按照要求构建新代码。
C++代码:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main() {
int N;
cin >> N;
while (N--) {
string code;
cin >> code;
long long sum = 0;
string result;
for (char c : code) {
if (isupper(c)) {
result += c;
} else if (isdigit(c)) {
string num;
while (isdigit(c)) {
num += c;
c = next(code.begin(), distance(code.begin(), &c) + 1)->operator *();
}
sum += stoll(num);
}
}
result += to_string(sum);
cout << result << endl;
}
return 0;
}
题目 J4: Sunny Days
思路讲解:
本题要求找到最长的连续晴天序列,假设只有一天的数据是错误的。我们可以通过计算每个可能的错误日对最长晴天序列的影响来解决这个问题。首先,找到所有连续的晴天序列;然后,尝试将每个非晴天(P)转换为晴天(S),计算可能的最长晴天序列。
C++代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int N;
cin >> N;
vector<char> days(N);
for (int i = 0; i < N; ++i) {
cin >> days[i];
}
int maxConsecutive = 0;
int current = 0;
for (int i = 0; i < N; ++i) {
if (days[i] == 'S') {
current++;
} else {
maxConsecutive = max(maxConsecutive, current);
current = 0;
}
}
maxConsecutive = max(maxConsecutive, current);
int overallMax = 0;
for (int i = 0; i <= N; ++i) {
int temp = 0, tempMax = 0;
for (int j = i; j < N; ++j) {
if (days[j] == 'S') {
temp++;
} else {
tempMax = max(tempMax, temp);
temp = 0;
}
}
tempMax = max(tempMax, temp);
if (i > 0 && days[i - 1] == 'P') tempMax++;
overallMax = max(overallMax, tempMax);
}
cout << overallMax << endl;
return 0;
}
题目 J5: Connecting Territories
思路讲解:
本题要求在网格上找到从上到下的最小路径成本。网格上的每个单元格都有一个成本,成本按照一定模式重复。我们可以使用动态规划来解决这个问题,从第一行开始,逐步计算到达每一行每个单元格的最小成本。
C++代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int R, C, M;
cin >> R >> C >> M;
vector<vector<int>> cost(R, vector<int>(C));
for (int i = 0; i < R; ++i) {
for (int j = 0; j < C; ++j) {
cost[i][j] = (i * C + j + 1) % M;
if (cost[i][j] == 0) cost[i][j] = M;
}
}
vector<vector<int>> dp(R, vector<int>(C, 0));
for (int j = 0; j < C; ++j) {
dp[0][j] = cost[0][j];
}
for (int i = 1; i < R; ++i) {
for (int j = 0; j < C; ++j) {
int minCost = INT_MAX;
if (j > 0) minCost = min(minCost, dp[i - 1][j - 1]);
if (j < C - 1) minCost = min(minCost, dp[i - 1][j + 1]);
minCost = min(minCost, dp[i - 1][j]);
dp[i][j] = minCost + cost[i][j];
}
}
int result = INT_MAX;
for (int j = 0; j < C; ++j) {
result = min(result, dp[R - 1][j]);
}
cout << result << endl;
return 0;
}
这些题解和代码实现了每个题目的基本逻辑,可能需要根据具体的输入输出格式进行调整。