题解:学而思编程 疫苗接种
【题目来源】
学而思编程:疫苗接种
【题目描述】
小猴前去接种疫苗,注射完第一剂后,医生告诉他过 \(21\) 天后再来注射第二剂。给定接种第一剂疫苗的日期(以年月日的顺序表示),请输出注射第二剂的日期(同样以年月日的顺序表示)。
【输入】
一行三个整数 \(y,m,d\),其中 \(y\) 表示年份、\(m\) 表示月份、\(d\) 表示天数。
【输出】
一行三个整数,表示接种第二剂疫苗的日期。
【输入样例】
2021 3 12
【输出样例】
2021 4 2
【核心思想】
-
问题分析:给定接种第一剂疫苗的日期(年 \(y\)、月 \(m\)、日 \(d\)),求 \(21\) 天后的日期。这是一个日期模拟 + 闰年处理问题,关键在于正确处理月份天数和跨年情况。
-
算法选择:
- 逐日推进:循环 \(21\) 次,每次将日期加 \(1\),处理跨月、跨年
- 闰年判断:\(2\) 月天数根据闰年调整(\(28\) 或 \(29\) 天)
- 月份天数表:预存每月天数,方便跨月判断
-
关键步骤:
- 初始化:读取 \(y, m, d\)
- 闰年处理:
- 若 \((y \bmod 4 = 0\) 且 \(y \bmod 100 \neq 0)\) 或 \(y \bmod 400 = 0\):
month[2]++:闰年 \(2\) 月有 \(29\) 天
- 若 \((y \bmod 4 = 0\) 且 \(y \bmod 100 \neq 0)\) 或 \(y \bmod 400 = 0\):
- 逐日推进(循环 \(i\) 从 \(1\) 到 \(21\)):
d++:天数加 \(1\)- 若
d > month[m]:d = 1, m++(跨月,进入下月第 \(1\) 天) - 若
m > 12:m = 1, y++(跨年,进入下一年 \(1\) 月)
- 输出 \(y, m, d\)
-
时间/空间复杂度:
- 时间复杂度:\(O(21)\),固定循环次数
- 空间复杂度:\(O(1)\),仅需月份天数表
-
日期模拟的核心思想:
- 逐日推进的鲁棒性:每天加 \(1\) 并检查边界,自然处理跨月、跨年,无需复杂公式
- 闰年规则:四年一闰、百年不闰、四百年再闰,通过条件判断调整 \(2\) 月天数
- 预存月份表:
month[1..12]存储各月天数,避免大量if-else,跨月判断简洁 - 固定偏移量:\(21\) 天偏移量不大,逐日模拟完全可行;若偏移量极大(如数年),可用日期差公式优化
- 适用于"日期偏移计算"类问题,逐日模拟直观可靠,是处理复杂历法规则的基础方法
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int y, m, d; // 年、月、日
int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 每月天数
int main() // 主函数
{
cin >> y >> m >> d; // 输入起始年月日
if (y%4==0 && y%100 !=0 || y%400==0) // 判断是否为闰年
month[2]++; // 闰年2月有29天
for (int i=1; i<=21; i++) // 向后推移21天
{
d++; // 天数加1
if (d>month[m]) d=1, m++; // 如果天数超过当月天数,进入下个月
if (m>12) m = 1, y++; // 如果月份超过12,进入下一年
}
cout << y << " " << m << " " << d << endl; // 输出21天后的日期
return 0; // 程序正常结束
}
【运行结果】
2021 3 12
2021 4 2
浙公网安备 33010602011771号