计算给定时间经过3小时30分后的时间,注意24小时制和跨日取模,需考虑特殊的冒号输入。
OJ: roj
题目 ID: 10012
难度:入门
标签:模拟字符串
创建: 2026-10-10 01:40
更新: 2026-10-10 01:40
形式化题目
给定一个 24 小时制的时间
正解
思路
本题最简便的做法是将时间统一转换为距当天
- 计算输入时间的总分钟数:
。 - 比赛时长为 3 小时 30 分钟,即
分钟。 - 将原时间的分钟数加上
分钟后,因结果可能跨日,对一天总分钟数( )进行取模操作。 - 取模后的总分钟数转换回小时和分钟输出,即小时为
,分钟为 ,并格式化为两位数、不足补零。
代码
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-09 22:30
# update_at: 2026-10-10 00:05
import re
import sys
MATCH_MINUTES = 3 * 60 + 30 # 比赛时长 210 分钟
DAY_MINUTES = 24 * 60 # 一天的总分钟数 1440
def solve() -> None:
"""读入 hh:mm,输出加 3 小时 30 分钟后的时刻(跨日对一天 1440 分钟取模)。"""
# 按「非数字字符」切分:题面样例用全角「:」,std.cpp 用半角 ':',两种都要能解析。
parts = re.split(r'\D+', sys.stdin.read().strip())
if len(parts) < 2:
return
hour, minute = map(int, parts[:2])
total = (hour * 60 + minute + MATCH_MINUTES) % DAY_MINUTES
print(f'{total // 60:02d}:{total % 60:02d}')
if __name__ == '__main__':
solve()cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-09 22:30
* update_at: 2026-10-10 00:05
*/
// main.cpp:时间。
// 比赛时长固定 3 小时 30 分 = 210 分钟。把开始时刻换算成「距当天 00:00 的分钟数」,
// 加上 210 分钟后对一天的总分钟数 1440 取模(跨日回卷),再换算回 hh:mm 并补前导零。
// ★ 冒号兼容:题面 PDF 的样例里冒号是全角「:」(U+FF1A,advance 1.0 em),
// 而官方参考实现 std.cpp 用的是半角 ':'(scanf("%d:%d"))。此处不区分冒号形式 ——
// 只认数字字符,分隔符一律跳过,故两种冒号下都与 std.cpp 语义一致。
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
typedef long long ll;
const ll MATCH_MINUTES = 3 * 60 + 30; // 比赛时长 210 分钟
const ll DAY_MINUTES = 24 * 60; // 一天的总分钟数 1440
// 从一行里取出小时和分钟:连续的数字段就是这两个数,中间的分隔符直接跳过。
// 结果通过引用带出,避免为一对返回值引入额外的结构。
void read_time(ll &hour, ll &minute) {
string line;
getline(cin, line);
bool in_hour = true; // 当前数字归小时(false 表示归分钟)
bool seen_digit = false; // 本段是否已读到数字,用来判断「分隔符是否已出现」
for (ll i = 0, len = line.size(); i < len; i++) {
char ch = line[i];
if ('0' <= ch && ch <= '9') {
if (in_hour) hour = hour * 10 + (ch - '0');
else minute = minute * 10 + (ch - '0');
seen_digit = true;
} else if (seen_digit && in_hour) {
in_hour = false; // 小时那段读完 ⇒ 后面的数字都归分钟
seen_digit = false;
}
}
}
void solve() {
ll hour = 0, minute = 0;
read_time(hour, minute);
ll total = (hour * 60 + minute + MATCH_MINUTES) % DAY_MINUTES; // 跨日对 1440 取模
cout << setfill('0') << setw(2) << total / 60 << ":"
<< setfill('0') << setw(2) << total % 60 << "\n";
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
solve();
return 0;
}复杂度
- 时间复杂度:
。只进行了常数次的算术运算。 - 空间复杂度:
。仅使用少量的整型变量。
总结
- 算法与复杂度:将时间换算成分钟后加上
,对 取模,然后再转回 ,均为常数时间操作,时空复杂度均为 。 - 冒号之谜的三层独立证据:题面样例中出现了全角冒号
:。通过三层证据确认真实数据应为半角冒号::- PDF CMap:ToUnicode 映射显示样例块用的是
<FF1A>全角(0x6F21),格式行用的是<003A>半角(0x01E3),两者并非解析错误。 - 字体 Advance 宽度:样例块冒号宽
1.00 em,格式行宽0.43 em,视觉与排版上严格区分。 - 参考代码与文件字节:
std.cpp使用scanf("%d:%d")(字面量为半角),且内部非 ASCII 字节数为 0。可以判定样例块的全角冒号仅是 Word 导出 PDF 时的排版副产物。
- PDF CMap:ToUnicode 映射显示样例块用的是
- 鲁棒的落盘实现策略:虽然官方
std.cpp的实现采用窄解析(遇到全角会解析失败导致变量未初始化,如23:31;空输入则产生未初始化 UB 如14:43),但因题面样例使用了全角,落盘代码选择了“更宽容、按题面为主”的鲁棒策略。相比std.cpp的窄解析,落盘代码在 6 个对照点上具有以下差异:- 合法半角(如
20:30):完全一致(1440组)。 - 全角冒号(如
20:30):std.cpp解析失败,落盘按题面样例语义修正并解析正确。 - 空格分隔(如
00 30):std.cpp解析错误,落盘兼容正确。 - 无分隔符(如
0000):std.cpp解析错误,落盘兼容正确。 - 空输入:
std.cpp产生未初始化 UB,落盘行为确定。 - 多行输入:两者均只处理第一组数据,表现一致。
- 合法半角(如
V1变异体双面结果与验证:- 变体 D(只认半角冒号):在半角 1440 组测试中 0 失败(即未承重),但在全角 1440 组测试中触发 1437 失败。这凸显了“仅半角数据无法鉴别冒号处理漏洞”以及同源同错的风险点。
- 其余变异:变体 A(加 3 小时没加 30 分钟)1440 组全失败;变体 B(去掉模 1440)暴露 210 组失败(
20:30~23:59);变体 C(输出不补 0)暴露 740 组失败;变体 E(输出全角冒号)1440 组全失败。
- 穷举验证与异源对比:测试覆盖了
共 1440 种时间的半角与全角输入(合计 2880 组数据)。落盘的 main.cpp与main.py均实现 0 分歧。此外,引入两个完全异源的参考代码(ref_carry.cpp:分/时各自独立进位;ref_step.cpp:逐分钟推进走 210 步)也达到了 0 分歧,它们未走主解“距0点总分钟数取模”的推导路径,作为必要补充进一步确保了解法的严密性。 - 证据强度声明:本题无本地数据(
data/为空,属于静默空转,零证据),验证基准依赖官方std.cpp。因其强度高于自写 ref,可作为可信锚点。但残留边界为其本身也被假设为正确(前述其处理全角/空输入有缺陷)。 V9内存安全与T38环境限制:对 1440 组合法输入(含极值与 )进行 main.cpp测试,UBSanstderr全空,无 UB。对照组control_ub.cpp有效报警,探针有效。资源符合config.json限制(1000ms / 128MB)。T9规范验证:- 极值处理:正确覆盖跨日边界输入如
等。 - 数据类型:计算最大值为
,在 int范围内无溢出。 - 数组边界:未使用数组,无越界风险。
- 变量初始化:妥善处理读取与转换,规避了原生
scanf解析失败带来的未初始化 UB 问题。 - 输入输出:对补零与换行等输出细节严格把关。
- 极值处理:正确覆盖跨日边界输入如