[2020蓝桥杯省赛B组]试题G:回文日期
这是一道难度比较简单的题目,数据规模较小,用暴力的方法也能破解,只是处理的过程较为繁琐。我一开始的想法是日期逐天增加,直到找到满足的答案为止。但这种方法很低级暴力,实在是想不出来好的方法才打算采用。我们其实不难发现一个规律:回文日期和 ABABBABA 型的回文日期的格式是固定,利用这种格式的特点,我们可以分别由前面4位和2位数字构造出新的日期,再对日期的合法性就行检验,如果不是合法的日期格式,再改变前面4位或2位数字继续构造日期,这样对8位数的处理就变成4位和2位,对答案的求解我个人认为是有加速作用的(如果理解有误希望大家斧正)。
问题描述
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。
输入描述
输入包含一个八位整数 NN,表示日期。
对于所有评测用例,10000101 \leq N \leq 8999123110000101≤N≤89991231,保证 NN 是一个合法日期的 8 位数表示。
输出描述
输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。
输入输出样例
示例
输入
20200202
输出
20211202
21211212
运行限制
最大运行时间:1s
最大运行内存: 256M
个人代码
#include <iostream>
using namespace std;
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//check函数用来检查得到的日期是否合法
bool check(int date)
{
int year = date/10000;
int month = (date/100)%100;
int day = date%100;
if(month < 0 || month > 12) return false;
if(day == 0 || month != 2 && day > days[month]) return false;
if(month==2)
{
int leap = year%4==0&&year%100!=0||year%400==0;
if(day>days[month]+leap) return false;
}
return true;
}
int main()
{
int N;
int date1,date2;
cin>>N;
int year = N/10000;
for(int i=year;;++i)
{
date1=i;
int x=i;
for(int j=0;j<4;++j)
{
date1 = date1*10+x%10;
x/=10;
}
if(date1>N&&check(date1))
{
cout<<date1<<endl;
break;
}
}
int ab=N/1000000;
for(int i=ab;;++i)
{
int a=i/10;
int b=i%10;
int x=b*10+a;
date2 = i*1000000+ i*10000 +x*100 +x;
if(date2>N&&check(date2))
{
cout<<date2<<endl;
break;
}
}
return 0;
}
个人总结:
如果平时不坚持敲代码,这种题目在赛场上就比较搞心态。呜呜呜,生命不止,coding不息。