题目描述:
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。
因为如果将这个日期按 “yyyymmdd
” 的格式写成一个 88 位数是 20200202
,恰好是一个回文数。
我们称这样的日期是回文日期。
有人表示 20200202
是“千年一遇” 的特殊日子。
对此小明很不认同,因为不到 22 年之后就是下一个回文日期:20211202
即2021 年 12 月 2 日。
也有人表示 20200202
并不仅仅是一个回文日期,还是一个 ABABBABA
型的回文日期。
对此小明也不认同,因为大约 100100 年后就能遇到下一个 ABABBABA
型的回文日期:21211212
即 2121 年 12月 12日。
算不上“千年一遇”,顶多算“千年两遇”。
给定一个 88 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA
型的回文日期各是哪一天。
注意: 本题数据保证一定有解。
注意:
下一个回文日期和下一个 ABABBABA
型的回文日期可能是同一天。
ABABBABA
型的回文日期,需要满足 A≠B。
输入格式:
输入包含一个八位整数 N,表示日期。
输出格式:
输出两行,每行 1 个八位数。
第一行表示下一个回文日期,第二行表示下一个 ABABBABA
型的回文日期。
数据范围:
对于所有评测用例,10000101≤N≤89991231,保证 N 是一个合法日期的 8 位数表示。
输入样例:
20200202
输出样例:
20211202
21211212
分析步骤:
第一:经过我的前两篇博文(日期差值,日期问题这里是链接)已经了解了,日期问题其实就两类:一种计算两个时间点相差多少天;第二种是计算有多少天是符合条件的;那么这道题就是两者的结合,对于学过我前两篇博文的同学,这道题应该可以写个七七八八。如果没看过大家可以去看看。
第二:我们先输入值,以他的下一天为起始点向后遍历。首先去判断他是否符合正常的日期;其次判断是否符合回文日期的特点以及是否是第一次出现;之后再去判断是否是难得一遇的日期以及是否是第一次出现。是的话就打印出来。
int main()
{
cin>>n;
for(int i = n + 1 ;; i++){
if(check(i)){
string str = to_string(i);
if(check1(str) and ! flag1){
flag1 = true;
cout<<i<<endl;
}
if(check2(str) and !flag2){
flag2 = true;
cout<<i<<endl;
return 0;
}
}
}
return 0;
}
第三: 先去书写check()检查一下是否是正常的日期,我们只需要把生活经验带到代码中就可以。
把year,month,day求出来。
如果日期为0,月份小于等于0或者大于12都是不可能的,正常的日期是不可能出现这些情况的。
如果month != 2 并且 日期 > 正常的月份日期的话也是不可能的。
如果month == 2 如果当年是闰年的话则日期不可以大于29否则不可以大于28
bool check(int date){
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if(!day || month <= 0 || month > 12 ) return false;
if(month != 2 && day >months[month]) return false;
if(month == 2)
{
if((year%4==0&&year%100!=0)||(year%400==0)) //闰年特判
{
if(day > 29) return false;
}
else
{
if(day > 28) return false;
}
}
return true;
}
第四:在是正确的日期下我们就可以判断是不是回文日期,运用了双指针的方法从两端开始对比只要有不一样的就返回false,只有全部对了才可以返回true。
bool check1(string str){
for(int i = 0 , j = 7 ; i <= j ; i++ , j-- ){
if(str[i] != str[j]) return false;
}
return true;
}
第五:在是正确的日期下我们就可以判断是不是难得一遇的回文日期我们可以把前四项取出来,并且互相对比只有1和3项一样;2和4项一样;1和2项不一样。这样才是难得一遇回文日期。
bool check2(string str){
if(check1(str)){
char a = str[0] , b = str[1] , c = str[2] , d = str[3];
if(a == c and b == d and a != b) return true;
}
return false;
}
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int n;
bool flag1 , flag2;
bool check(int date){
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if(!day || month <= 0 || month > 12 ) return false;
if(month != 2 && day >months[month]) return false;
if(month == 2)
{
if((year%4==0&&year%100!=0)||(year%400==0)) //闰年特判
{
if(day > 29) return false;
}
else
{
if(day > 28) return false;
}
}
return true;
}
bool check1(string str){
for(int i = 0 , j = 7 ; i <= j ; i++ , j-- ){
if(str[i] != str[j]) return false;
}
return true;
}
bool check2(string str){
if(check1(str)){
char a = str[0] , b = str[1] , c = str[2] , d = str[3];
if(a == c and b == d and a != b) return true;
}
return false;
}
int main()
{
cin>>n;
for(int i = n + 1 ;; i++){
if(check(i)){
string str = to_string(i);
if(check1(str) and ! flag1){
flag1 = true;
cout<<i<<endl;
}
if(check2(str) and !flag2){
flag2 = true;
cout<<i<<endl;
return 0;
}
}
}
return 0;
}