LQ0150 回文日期枚举
Posted 海岛Blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 <stdio.h>
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;
AC的C语言程序(多输入)如下:
/* LQ0150 回文日期 */
#include <stdio.h>
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;
AC的C语言程序(简单暴力)如下:
/* LQ0150 回文日期 */
#include <stdio.h>
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;
以上是关于LQ0150 回文日期枚举的主要内容,如果未能解决你的问题,请参考以下文章