CSP历年复赛题-P2010 [NOIP2016 普及组] 回文日期

原题链接:https://www.luogu.com.cn/problem/P2010

题意解读:计算两个日期之间有多少个日期是回文。

解题思路:

如果通过枚举两个日期之间的所有日期,然后判断回文,则会有几个问题:

枚举数据规模在10^7级别,再加上对于日期加一天、判断回文等处理,有可能超时,而且对日期进行加一天、判断回文等操作都比较麻烦。

换一种枚举思路:

由于年开头数字不为0,年的范围是1000~9999,如果是回文日期,日期的年部分翻转后就是月日部分

所以只需要枚举年:1000~9999,就可以产生所有的可能的回文日期

但是对于一个年,翻转后生成的日期不一定是一个有效日期(开始日期<=日期<=结束日期,1<=月<=12,1<=日<=年月对应的最大天数)

因此,只需要将所有年进行翻转,然后和年拼接生成一个日期,判断该日期是否有效,如果有效就数量累加。

100分代码:

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

int date1, date2;
int ans;

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

//判断year是否是闰年
bool isleap(int year)
{
    return year % 100 != 0 && year % 4 == 0 || year % 400 == 0;
}

//获取year年month月的天数
int getdays(int year, int month)
{
    if(isleap(year))
    {
        int days = month_days[month];
        if(month == 2) days++;
        return days;
    }
    else return month_days[month];
}

//检查日期是否有效
bool check(int date)
{
    if(date < date1 || date > date2) return false;
    int year = date / 10000;
    int month = (date / 100) % 100;
    int day = date % 100;
    if(month < 1 || month > 12) return false;
    if(day < 1 || day > getdays(year, month)) return false;
    return true;
}

int main()
{
    cin >> date1 >> date2;
    for(int i = 1000; i <= 9999; i++)
    {
        int year = i;
        //将year和year翻转之后的数字拼接成date
        int date = year * 10000;
        date += (year % 10) * 1000;
        date += (year / 10 % 10) * 100;
        date += (year / 100 % 10) * 10;
        date += year / 1000;
    
        if(check(date)) ans++;
    }
    cout << ans;

    return 0;
}

 

posted @ 2024-06-06 12:55  五月江城  阅读(64)  评论(0编辑  收藏  举报