蓝桥杯-回文日期(两种写法)

在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。

牛牛习惯用 8 位数字表示一个日期,其中,前 4 位代表年份,接下来 2 位代表月份,最后 2 位代表日期。

显然:一个日期只有一种表示方法,而两个不同的日期的表示方法不会相同。

牛牛认为,一个日期是回文的,当且仅当表示这个日期的 8 位数字是回文的。

现在,牛牛想知道:在他指定的两个日期之间(包含这两个日期本身),有多少个真实存在的日期是回文的。

一个 8 位数字是回文的,当且仅当对于所有的 i
(1≤i≤8) 从左向右数的第 i 个数字和第 9−i 个数字(即从右向左数的第 i 个数字)是相同的。

例如:

对于 2016 年 11 月 19 日,用 8 位数字 20161119 表示,它不是回文的。
对于 2010 年 1 月 2 日,用 8 位数字 20100102 表示,它是回文的。
对于 2010 年 10 月 2 日,用 8 位数字 20101002 表示,它不是回文的。

输入格式

输入包括两行,每行包括一个 8 位数字

第一行表示牛牛指定的起始日期 date1,第二行表示牛牛指定的终止日期 date2。保证 date1 和 date2 都是真实存在的日期,且年份部分一定为 4 位数字,且首位数字不为 0。

保证 date1 一定不晚于 date2。

输出格式

输出共一行,包含一个整数,表示在 date1 和 date2 之间,有多少个日期是回文的。

输入样例:

20110101
20111231

输出样例:

1

题解:

一共有两种写法:

  1. 枚举前四位数, 后四位是前四位的回文, 判断这个日期是否是合法的,以及是否在开始日期和结束日期之间
  2. 枚举后四位数, 前四位是后四位的会问, 判断这个日期是否在开始日期和结束日期之间

之所以第2种没有判断这个日期是否合法, 是因为 后四位是month和day, 它们各个位的数据范围不超过3, day最大是31, month最大是12, 而前四位各个位最大都可以是9, 所以date一定合法

枚举前四位
ac代码👇

#include <bits/stdc++.h>
using namespace std;

int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

bool check(int date)
{
    int year = date / 10000;
    int month = date % 10000 / 100;
    int day = date % 100;
    
    if (month <= 0 || month >= 13 || day <= 0 || day >= 32) return false;

    // 二月需要特殊处理
    // 是闰年, 且2月的day > 29
    if ((year % 2 == 0 && year % 100 != 0 || year % 400 == 0) && month == 2 && day > 29) return false;

    // 不是闰年, 且2月的day > 28
    if (!(year % 2 == 0 && year % 100 != 0 || year % 400 == 0) && month == 2 && day > 28) return false;

    // 除了二月, 其他月份的day大于 days
    if (month != 2 && day > days[month]) return false;
    
    return true;
}

int main()
{
    int a, b; cin >> a >> b;
    
    int res = 0;
    for (int i = 0; i <= 9999; i ++)
    {           // 👇日期的前四位 👇 日期的第五位       👇日期的第6位         👇日期的第7位        👇日期的第8位
        int date = i * 10000 +     1000 * (i % 10) +   100 * (i / 10 % 10) + 10 * (i / 100 % 10) + i / 1000;

        if (date >= a && date <= b && check(date)) res ++;
    }
    
    cout << res << endl;
    return 0;
}

枚举后四位

注意事项:

  • 如果mouth是2并且满足时回文的话, 那么一定是闰年, 因为 mouth是2时的回文数列中 year的后两位一定是20, 即 xx20

ac代码👇

#include <bits/stdc++.h>
using namespace std;

int days[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int main()
{
    int a, b; cin >> a >> b;
    
    int res = 0;
    for (int mouths = 1; mouths <= 12; mouths ++)
        for (int day = 1; day <= days[mouths]; day ++)
        {               // 👇 取 day 的第一位    👇取day的第二位  👇 取mouths的第一位  👇取mouths的第二位
            int year = 1000 * (day % 10) + 100 * (day / 10) + 10 * (mouths % 10) + mouths / 10;
            int date = year * 10000 + mouths * 100 + day;
            if (date >= a && date <= b) res ++;
        }
    cout << res << endl;
    return 0;
}

觉得写的不错的话, 点个赞吧~

热门相关:有钱的干爹   韩国版肉蒲团   姆明谷的夏祭   精力旺盛的公公   巾帼风云