文章目录
- 前言
- 1. 如何枚举合法日期
- 1.1 预存每个月的天数
- 1.2 封装一个判断日期是否合法的函数
- 1.3 枚举日期并判断日期是否合法
- 2. 判断日期是否为回文日期
- 2.1 将日期当作字符串进行处理
- 2.2 将日期当作一个8位数进行处理
- 3. 给定初始日期,计算经过n天后对应的日期
- 3.1 得到某年某月的天数
- 3.2 计算经过n天后的日期
- 4. 练习
- 4.1 回文日期
- 4.2 跑步锻炼
- 4.3 日期统计
- 4.4 回文日期
- 5. 拓展-与时间相关的题目
- 5.1 例题
- 5.1.1 题目描述
- 5.1.2 题目链接
- 5.2 解题思路
- 5.3 参考题解
前言
纵观蓝桥杯近几年的真题,与日期相关的题目经常出现
为了节省我们宝贵的比赛时间,对于与日期相关的题目,我们需要构造一套属于自己的模版
1. 如何枚举合法日期
对于日期,我们一般把它当作一个8位的数字进行处理,前四位数字是年份,第五位和第六位数字是月份,最后两位数字是当前月份的天数
一般是先枚举日期,再判断日期是否合法
1.1 预存每个月的天数
创建一个全局范围的数组,用于预存每个月的天数。
之所以要创建全局范围的数组,是为了避免函数之间的传参操作。
int days[15] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1.2 封装一个判断日期是否合法的函数
bool isLegal(int date) {
int year = date / 10000;
int month = date / 100 % 100;
int day = date % 100;
if (month > 12 || month < 1) {
return false;
}
if (day < 1 || day > 31) {
return false;
}
int isLeap = 0;
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
isLeap = 1;
}
if (month == 2) {
if (day > days[month] + isLeap) {
return false;
}
} else {
if (day > days[month]) {
return false;
}
}
return true;
}
1.3 枚举日期并判断日期是否合法
以2024年为例,枚举2024年的所有合法日期
#include <iostream>
using namespace std;
int days[15] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool isLegal(int date) {
int year = date / 10000;
int month = date / 100 % 100;
int day = date % 100;
if (month > 12 || month < 1) {
return false;
}
if (day < 1 || day > 31) {
return false;
}
int isLeap = 0;
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
isLeap = 1;
}
if (month == 2) {
if (day > days[month] + isLeap) {
return false;
}
} else {
if (day > days[month]) {
return false;
}
}
return true;
}
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for (int i = 20240101; i <= 20241231; i++) {
if (isLegal(i)) {
cout << i << endl;
}
}
return 0;
}
2. 判断日期是否为回文日期
方法2.2的运行效率远高于方法2.1
如果开始日期和结束日期相差超过100年,建议使用方法2.2
2.1 将日期当作字符串进行处理
要判断一个日期是否是回文日期,可以先将该日期转成字符串
将反转后的字符串与原字符串对比,如果相等则说明该日期是回文日期
该方法需要包含<string>
头文件和<algorithm>
头文件,而且C++的版本要大于等于C++11
bool check01(int date) {
string str = to_string(date);
string temp = str;
reverse(temp.begin(), temp.end());
return str == temp;
}
check01函数也可写成下面的形式(无需包含<algorithm>
头文件)
bool check01(int date) {
string str = to_string(date);
if (str[0] == str[7] && str[1] == str[6] && str[2] == str[5] && str[3] == str[4]) {
return true;
}
return false;
}
2.2 将日期当作一个8位数进行处理
将日期当作一个8位数的整数,利用基础的运算符号反转整数,然后判断反转后的整数与原整数是否相等
bool check02(int date) {
int originalNumber = date;
int reverseNumber = 0;
while (date != 0) {
reverseNumber = reverseNumber * 10 + date % 10;
date = date / 10;
}
return originalNumber == reverseNumber;
}
以下例子求的是1949年到2049年之间的所有回文日期
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int days[15] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool isLegal(int date) {
int year = date / 10000;
int month = date / 100 % 100;
int day = date % 100;
if (month > 12 || month < 1) {
return false;
}
if (day < 1 || day > 31) {
return false;
}
int isLeap = 0;
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
isLeap = 1;
}
if (month == 2) {
if (day > days[month] + isLeap) {
return false;
}
} else {
if (day > days[month]) {
return false;
}
}
return true;
}
bool check01(int date) {
string str = to_string(date);
string temp = str;
reverse(temp.begin(), temp.end());
return str == temp;
}
bool check02(int date) {
int originalNumber = date;
int reverseNumber = 0;
while (date != 0) {
reverseNumber = reverseNumber * 10 + date % 10;
date = date / 10;
}
return originalNumber == reverseNumber;
}
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for (int i = 19490101; i <= 20491231; i++) {
if (isLegal(i) && check02(i)) {
cout << i << endl;
}
}
return 0;
}
3. 给定初始日期,计算经过n天后对应的日期
3.1 得到某年某月的天数
int getDay(int year, int month) {
if (month != 2) {
return days[month];
} else {
int leap = year % 400 || (year % 4 == 0 && year % 100 != 0);
return 28 + leap;
}
}
3.2 计算经过n天后的日期
int pass(int startDate, int n) {
int year = startDate / 10000;
int month = startDate / 100 % 100;
int day = startDate % 100;
for (int i = 1; i <= n; i++) {
day++;
if (day > getDay(year, month)) {
month++;
day = 1;
}
if (month > 12) {
year++;
month = 1;
}
}
return year * 10000 + month * 100 + day;
}
4. 练习
4.1 回文日期
题目链接:回文日期
4.2 跑步锻炼
题目链接:跑步锻炼
4.3 日期统计
题目链接:日期统计
4.4 回文日期
题目链接:回文日期
5. 拓展-与时间相关的题目
处理时间一般会使用到运用求余、除法这两种基本运算
5.1 例题
5.1.1 题目描述
5.1.2 题目链接
题目链接:时间显示
5.2 解题思路
-
用
long long
类型的数据接收数据 -
由于题目给出的时间是以毫秒为单位的,因此要先将时间除以1000变成以秒为单位
-
因为不需要显示年、月、日,所以要先过滤掉年、月、日的秒数
-
最后,利用求余、除法运算得到时、分、秒
5.3 参考题解
时、分、秒不足两位时要补前导0
#include <cstdio>
using namespace std;
int main() {
long long time;
scanf("%lld", &time);
time = time / 1000; // 将以毫秒为单位转化为以秒为单位
time = time % (60 * 60 * 24); // 过滤掉年、月、日的秒数
long long hour = time / 3600; // 一小时3600秒
long long minute = time / 60 % 60; // 一分钟60秒
long long second = time % 60;
printf("%02lld:%02lld:%02lld", hour, minute, second);
return 0;
}