题目:链接
题意
给定一个日期,求出该日期后下一个回文日期和ABABBABA型的回文日期。回文日期:如:20211202;ABABBABA型的回文日期:如:20200202。
思路
1、回文日期如何读取,如何使用?这就涉及字符串转整数,整数转字符串的问题。2、如何正确遍历每一个日期?需要注意两点,第一日期是否合法,至于是否合法重点关注天数即可,第二如果是从给定日期的那年开始遍历,本年本月要特殊处理,其他年份则可从头开始。3、回文日期的判断,ABABBABA型的回文日期可以在回文日期的基础上直接判断0,2位置和1,3位置是否相同。4、注意闰年。
心得
模拟题不难,也没有什么特别的算法,但就是复杂、繁琐,需要考虑的条件特别多。本题可以积累,整数与字符串的相互转化函数,回文日期判断函数,一起八位日期遍历方式。
代码
#include <bits/stdc++.h>
using namespace std;
int s2i(string s)
{
int res = 0;
for(const auto&i:s) res = 10 * res + i -'0';
return res;
}
string i2s(int x, int w)
{
string s;
while(x)
s += x % 10 +'0', x /= 10;
while(s.length() < w) s += '0';
reverse(s.begin(), s.end());
return s;
}
bool isleapyear(int year)
{
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}
bool isok(int year, int month, int day)
{
int days[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
if(isleapyear(year)) days[2]=29;
return day <= days[month];
}
bool isPa(string s)
{
for(int i = 0; i < s.length()/2; i++)
if(s[i] != s[s.length() - i - 1]) return false;
return true;
}
bool isPa2(string s)
{
if(!isPa(s)) return false;
return s[0] == s[2] && s[1] == s[3];
}
int main()
{
string s;cin>>s;
int year = s2i(s.substr(0,4)), month = s2i(s.substr(4,2)), day = s2i(s.substr(6,2));
bool ans1 = false, ans2 = false;
for(int i = year; i <= 9999; i++)
{
for(int j = 1; j <= 12; j++)
{
if(i == year && j < month) continue;
for(int k = 1; k <= 31; k++)
{
if(i == year && j == month && k <= day) continue;
if(!isok(i, j, k)) continue;
string data = i2s(i, 4) + i2s(j, 2) + i2s(k, 2);
if(!ans1 && isPa(data))
{
cout<<data<<'\n';
ans1 = true;
}
if(!ans2 && isPa2(data))
{
cout<<data<<'\n';
ans2 = true;
}
}
}
}
return 0;
}