CSP历年复赛题-P2010 [NOIP2016 普及组] 回文日期
原题链接:https://www.luogu.com.cn/problem/P2010
题意解读:计算两个日期之间有多少个日期是回文。
解题思路:
如果通过枚举两个日期之间的所有日期,然后判断回文,则会有几个问题:
枚举数据规模在10^7级别,再加上对于日期加一天、判断回文等处理,有可能超时,而且对日期进行加一天、判断回文等操作都比较麻烦。
换一种枚举思路:
由于年开头数字不为0,年的范围是1000~9999,如果是回文日期,日期的年部分翻转后就是月日部分
所以只需要枚举年:1000~9999,就可以产生所有的可能的回文日期
但是对于一个年,翻转后生成的日期不一定是一个有效日期(开始日期<=日期<=结束日期,1<=月<=12,1<=日<=年月对应的最大天数)
因此,只需要将所有年进行翻转,然后和年拼接生成一个日期,判断该日期是否有效,如果有效就数量累加。
100分代码:
#include <bits/stdc++.h>
using namespace std;
int date1, date2;
int ans;
int month_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//判断year是否是闰年
bool isleap(int year)
{
return year % 100 != 0 && year % 4 == 0 || year % 400 == 0;
}
//获取year年month月的天数
int getdays(int year, int month)
{
if(isleap(year))
{
int days = month_days[month];
if(month == 2) days++;
return days;
}
else return month_days[month];
}
//检查日期是否有效
bool check(int date)
{
if(date < date1 || date > date2) return false;
int year = date / 10000;
int month = (date / 100) % 100;
int day = date % 100;
if(month < 1 || month > 12) return false;
if(day < 1 || day > getdays(year, month)) return false;
return true;
}
int main()
{
cin >> date1 >> date2;
for(int i = 1000; i <= 9999; i++)
{
int year = i;
//将year和year翻转之后的数字拼接成date
int date = year * 10000;
date += (year % 10) * 1000;
date += (year / 10 % 10) * 100;
date += (year / 100 % 10) * 10;
date += year / 1000;
if(check(date)) ans++;
}
cout << ans;
return 0;
}
分类:
CSP-J复赛真题解析
标签:
枚举
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?