• LQ0150 回文日期【枚举】


    题目来源:蓝桥杯2020初赛 C++ A组G题

    题目描述
    2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期

    有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。

    也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。

    给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

    输入描述
    输入包含一个八位整数 N,表示日期。

    对于所有评测用例,10000101≤N≤89991231,保证 N 是一个合法日期的 8 位数表示。

    输出描述
    输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。

    输入输出样例
    输入
    20200202
    输出
    20211202
    21211212

    问题分析
    这个题蓝桥杯官网的测试数据有BUG,N的最大值应该是99991231而不是89991231,否则AC不了。
    一种方法是暴力法,速度比较慢。枚举的日期从N+1到99991231。
    另外一种是根据约束条件进行枚举,月份的第1位只能是0或1。而年的最后一位对应月份的第1位,枚举年的话,只需要考虑年的最后1位是0或1,枚举的数量就少多了。
    有T个输入的情形(网站http://oj.ecustacm.cn/),用后一种解法改造后可以通过,不会出现TLE(超时)。这里也给出有关的题解。

    AC的C语言程序(枚举年)如下:

    /* LQ0150 回文日期 */
    
    #include 
    
    int mdays[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    int judge(int y, int m, int d)
    {
        if (1 <= m && m <= 12) {
            int md = mdays[m];
            if (m == 2)
                md += (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
            if (1 <= d && d <= md)
                return 1;
        }
        return 0;
    }
    
    int reverse(int n)
    {
        int ret = 0;
        for (int i = 1; i <= 4; i++)
            ret *= 10, ret += n % 10, n /= 10;
        return ret;
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);
    
        int year = n / 10000, date1 = 0, date2 = 0;
        for (int y = (year / 10) * 10; y <= 9999; y += 10) {
            int md = reverse(y);
            if (y * 10000 + md > n) {
                int month = md / 100;
                int day = md % 100;
                if (judge(y, month, day)) {
                    if (date1 == 0) date1 = y * 10000 + md;
                    if (date2 == 0 && month == day) date2 = y * 10000 + md;
                    if (date1 && date2) break;
                }
            }
    
            int y1 = y + 1;
            md = reverse(y1);
            if (y1 * 10000 + md > n) {
                int month = md / 100;
                int day = md % 100;
                if (judge(y1, month, day)) {
                    if (date1 == 0) date1 = y1 * 10000 + md;
                    if (date2 == 0 && month == day) date2 = y1 * 10000 + md;
                    if (date1 && date2) break;
                }
            }
        }
    
        printf("%08d\n%08d\n", date1, date2);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    AC的C语言程序(多输入)如下:

    /* LQ0150 回文日期 */
    
    #include 
    
    int mdays[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    int judge(int y, int m, int d)
    {
        if (1 <= m && m <= 12) {
            int md = mdays[m];
            if (m == 2)
                md += (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
            if (1 <= d && d <= md)
                return 1;
        }
        return 0;
    }
    
    int reverse(int n)
    {
        int ret = 0;
        for (int i = 1; i <= 4; i++)
            ret *= 10, ret += n % 10, n /= 10;
        return ret;
    }
    
    int main()
    {
        int t, n;
        scanf("%d", &t);
        while (t--) {
            scanf("%d", &n);
        
            int year = n / 10000, date1 = 0, date2 = 0;
            for (int y = (year / 10) * 10; y <= 9999; y += 10) {
                int md = reverse(y);
                if (y * 10000 + md > n) {
                    int month = md / 100;
                    int day = md % 100;
                    if (judge(y, month, day)) {
                        if (date1 == 0) date1 = y * 10000 + md;
                        if (date2 == 0 && month == day) date2 = y * 10000 + md;
                        if (date1 && date2) break;
                    }
                }
        
                int y1 = y + 1;
                md = reverse(y1);
                if (y1 * 10000 + md > n) {
                    int month = md / 100;
                    int day = md % 100;
                    if (judge(y1, month, day)) {
                        if (date1 == 0) date1 = y1 * 10000 + md;
                        if (date2 == 0 && month == day) date2 = y1 * 10000 + md;
                        if (date1 && date2) break;
                    }
                }
            }
        
            printf("%08d\n%08d\n", date1, date2);
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    AC的C语言程序(简单暴力)如下:

    /* LQ0150 回文日期 */
    
    #include 
    
    int mdays[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    int judge(int y, int m, int d)
    {
        if (1 <= m && m <= 12) {
            int md = mdays[m];
            if (m == 2)
                md += (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
            if (1 <= d && d <= md)
                return 1;
        }
        return 0;
    }
    
    int reverse(int n)
    {
        int ret = 0;
        for (int i = 1; i <= 4; i++)
            ret *= 10, ret += n % 10, n /= 10;
        return ret;
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);
    
        int date1 = 0, date2 = 0;
        for (int i = n + 1; i <= 99991231; i++) {
            int md = i % 10000;
            int year = i / 10000;
            int month = md / 100;
            int day = md % 100;
            if (judge(year, month, day) && md == reverse(year)) {
                if (date1 == 0) date1 = i;
                if (date2 == 0 && month == day) date2 = i;
            }
            if (date1 && date2) break;
        }
    
        printf("%08d\n%08d\n", date1, date2);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
  • 相关阅读:
    AnkiPDF Guru软件评测:打开全新学习方式的大门
    前端渲染后端返回的HTML格式的数据
    字符设备和杂项设备总结
    SHELL编程基础2
    MATLAB仿真通信系统的眼图
    手机备忘录可以设置密码吗 能锁屏加密的备忘录
    学习笔记3--高精度地图关键技术(上)
    致敬!百里煤海战斗在第二战线上的人们
    周末折腾了两天,踩了无数个坑,终于把win7装成了centos7
    商城系统APP如何开发 都有哪些步骤
  • 原文地址:https://blog.csdn.net/tigerisland45/article/details/127717698