题目:链接

题意

给定一个日期,求出该日期后下一个回文日期和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;
}