回文日期(牛客春招)
写在前面:

牛客每日一题持续更新中!
今天给亦菲晏讲的是 回文日期
题目如下:
描述
一个日期用YYYYMMDD的8位数字表示,其中前四位为年份,接着两位为月份,最后两位为日期
若这8位数字本身是一个回文数,则称该日期为回文日期
给定起始日期a与终止日期(均包含在内,且满足≤),请计算区间内真实存在的回文日期数量
名词解释回文数:一个数字从左往右读与从右往左读完全相同
日期合法性
● 1,3,5,7,8,10,12月有31天:
● 4,6,9,11 月有30天;
2月在年有29天,平年有28天
年判定
● 能被4整除但不能被100整除的年份;
● 或能被400整除的年份
输入描述:
第一行输入8位整数a,表示起始日期
第二行输入8位整数b,表示终止日期
输出描述:
输出一个整数,表示[a,区间内回文日期的数量
例1
输入:20110101
20111231
输出:1
说明:
在这个样例中,在20110101和20111231之间,回文日期有1个,即20111102
例2
输入:20000101
20101231
输出:2
说明:
在这个样例中,在20000101和20101231之间,回文日期有2个,即 20010002 和20100102
看完感觉可能挺麻烦的 其实并没有我们想的那么复杂
题意
- 计数两日期之间的回文日期
思路
- 枚举所有年份,构造月份判断是否合法
- 枚举所有月份和日期,构造年月日看是否在区间内
- 但是,构造年份检查月份还要分大小月以及平年闰年,相对麻烦,故构造年月日是更为便捷的解法
我们可以先 定义一个数组 用来存储 1-12月 每个月份的天数
int up[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
然后就开始构造回文年月日 判断是否在那个区间
代码如下:
C/C++版本:
#include<bits/stdc++.h>
using namespace std;int main(){int st, ed, ans = 0; // 起始日期,终止日期,计数器// 每个月的最大天数(2月按闰年处理为29天)int up[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};cin >> st >> ed; // 输入起始和终止日期// 遍历所有可能的月份和日期for(int i = 1; i < 13; i++){ // 月份从1到12for(int j = 1; j <= up[i]; j++){ // 日期从1到当月最大天数// 构建所有的回文日期:根据月日生成对应的年份int y = j % 10 * 1e7 + j / 10 * 1e6 + i % 10 * 1e5 + i / 10 * 1e4 + i * 100 + j;// 检查生成的日期是否在给定范围内if(y >= st && y <= ed) ans++;}}cout << ans; // 输出回文日期数量return 0;
}
Python版本:
def main():st = int(input().strip()) # 起始日期ed = int(input().strip()) # 终止日期ans = 0 # 计数器# 每个月的最大天数(2月按闰年处理为29天)month_days = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]# 遍历所有可能的月份和日期for month in range(1, 13): # 月份从1到12for day in range(1, month_days[month] + 1): # 日期从1到当月最大天数# 构建所有的回文日期:根据月日生成对应的年份# 例如:3月21日 → 1221 03 21 → 12210321year = (day % 10 * 10000000 + day // 10 * 1000000 + month % 10 * 100000 + month // 10 * 10000 + month * 100 + day)# 检查生成的日期是否在给定范围内if st <= year <= ed:ans += 1print(ans) # 输出回文日期数量if __name__ == "__main__":main()
Java版本:
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int st = scanner.nextInt(); // 起始日期int ed = scanner.nextInt(); // 终止日期int ans = 0; // 计数器// 每个月的最大天数(2月按闰年处理为29天)int[] monthDays = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 遍历所有可能的月份和日期for (int month = 1; month <= 12; month++) { // 月份从1到12for (int day = 1; day <= monthDays[month]; day++) { // 日期从1到当月最大天数// 构建所有的回文日期:根据月日生成对应的年份// 例如:3月21日 → 1221 03 21 → 12210321int year = day % 10 * 10000000 + day / 10 * 1000000 + month % 10 * 100000 + month / 10 * 10000 + month * 100 + day;// 检查生成的日期是否在给定范围内if (year >= st && year <= ed) {ans++;}}}System.out.println(ans); // 输出回文日期数量scanner.close();}
}
其实有些细节的亦菲彦祖们可能发现了 我吧每一个平年都当做了闰年
-
2025.4.19 枚举限制多的(月份),判断限制少的(年)
闰年的判断被规避了,92200229是闰年
所以还是有点漏洞的 但是这里样例没有那么多也没事
好了,各位码友,代码已经调试通过,文章也已commit,就等各位的push了。点赞不要 //TODO,关注务必 star!
写在最后:

