洛谷 P2010 【回文日期】题解

思路:模拟、枚举

这道题是 NOIP2016 PJ T2,作为普及组的第二题,我认为它对于普及组选手来说还是有一些难度的。

我没有想到 @「QQ红包」 管理员大佬那样枚举月日的 $ O(N^2) $ 做法,写成了三重循环,枚举年月日,然后再判断是否回文。然后就成为了最差解(

主要注释在代码中。

$ \rm code $

# include <bits/stdc++.h>
# define ll long long
# define rg register
# define il inline
# define mem(a, num) memset(a, num, sizeof(a))
# define debug(s, x) cout << s << " -> " << x << endl
const bool oj = true;
using namespace std;
template < typename T >
il void readInt(T &x) {
    x = 0; rg T f = 1; rg char ch = getchar();
    while(!isdigit(ch)) f = ch == '-' ? -1 : f, ch = getchar();
    while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
    x *= f;
}
template < typename T >
il int Max(T a, T b) {return a > b ? a : b;}
template < typename T >
il int Min(T a, T b) {return a < b ? a : b;}
void file() {
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
}
// ---head file--- //

int date1, date2; //两个日期
int xhw[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //每个月有多少天,二月份由于闰年的原因,需要特殊处理一下。
il void change(int); //修改二月份的日期的函数
il bool orz(int, int, int); //判断日期是否是回文数的函数
int main() {
    if(!oj) file();
    readInt(date1), readInt(date2);
# define y1 Y1 //因为 y1 这个变量跟 cmath 库中某个东西有冲突,所以先在这里 define 一下
    int y1 = date1 / 10000, y2 = date2 / 10000, m1 = date1 / 100 % 100, m2 = date2 / 100 % 100, d1 = date1 % 100, d2 = date2 % 100, ans = 0;
    //debug("y1", y1), debug("y2", y2), debug("m1", m1), debug("m2", m2), debug("d1", d1), debug("d2", d2);
    //以上是分解出两个日期的年、月、日
    for(rg int x = y1; x <= y2; ++x) { //枚举年
        int t1, t2;
        if(x == y1) t1 = m1;
        else t1 = 1;
        if(x == y2) t2 = m2;
        else t2 = 12; 
        //在枚举月份的时候,需要注意一下。大家可以自己试着理解一下,如果有不理解的,可以私信我。这里因为版面等原因不再阐述。
        for(int h = t1; h <= t2; ++h) { //枚举月
            if(h == 2) change(x); //如果是二月份,进入 change 函数
            for(int w = 1; w <= xhw[h]; ++w) //枚举日
                if(orz(x, h, w)) ++ans; //如果年月日回文,ans 累加。
        }
    }
    printf("%d", ans); //最后输出 ans 即可。
    return 0;
}
il void change(int x) {
    xhw[2] = (((x % 4 == 0) && (x % 100 != 0)) || (x % 400 == 0)) ? 29 : 28; //如果该年为闰年,二月的天数改为 29,否则为 28。
}
il bool orz(int x, int h, int w) {
    int a[10];
    a[1] = x / 1000, a[2] = x / 100 % 10, a[3] = x / 10 % 10, a[4] = x % 10, a[5] = h / 10, a[6] = h % 10, a[7] = w / 10, a[8] = w % 10;
    //分解出 8 位年月日中的每一位
    if(a[1] == a[8] && a[2] == a[7] && a[3] == a[6] && a[4] == a[5]) return true; //如果日期回文,返回 true
    return false; //否则,返回 false
}

 

posted @ 2019-06-11 22:07  Aehnuwx  阅读(395)  评论(0编辑  收藏  举报