测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A27947. 千年一遇对称日

填空题 中等

题目描述

千年一遇对称日

题目描述

在 2021 年 12 月 02 日这天(20211202),有人发了这么一张图,上书“千年一遇对称日,万事圆满在今朝”。话是挺吉利的,但好像下一个对称日并不需要等上一千年…… 下面任给一个人的生卒年份,请你列出来这个人一辈子经过的所有对称日。

输入

输入第一行给出一个人的名字,是由不超过30个字符的英文字母和空格组成的、以回车结束的非空字符串。第二行按 `yyyymmdd - yyyymmdd` 的格式给出这个人的生卒年(`yyyy`)、月(`mm`)、日(`dd`)。 虽然生卒日期可能是虚构的,但题目保证出生日期在去世日期之前,且每个日期都是合法的,从 `00010101` 到 `99991231`。注意这里遵循“四年一闰,百年不闰,四百年再闰”的规则定义闰年,即年份是 4 的倍数,且不是 100 的倍数的,为普通闰年;年份是整百数的,必须是 400 的倍数才是闰年。闰年跟普通年的区别就是 2 月有 29 天。

输出

首先在第一行原样输出这个人的名字。随后按照时间顺序,每行输出该人所经历的一个对称日,格式与输入格式相同。注意:生卒日期也包含在内。

输入样例

Katherine Johnson
19180826 - 20200224

输出样例

Katherine Johnson
20011002
20100102
20111102
20200202

参考答案

#include <stdio.h> #include <string.h> #include <stdbool.h> // 检查一个日期是否是对称日 bool isSymmetricDate(const char* date) { int len = strlen(date); for (int i = 0; i < len / 2; ++i) { if (date[i] != date[len - 1 - i]) { return false; } } return true; } // 检查一个日期是否合法 bool isValidDate(int year, int month, int day) { if (month < 1 || month > 12 || day < 1) { return false; } int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 判断闰年 if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { daysInMonth[1] = 29; // 闰年2月有29天 } return day <= daysInMonth[month - 1]; } // 将日期字符串转换为年、月、日 bool parseDate(const char* dateStr, int* year, int* month, int* day) { if (strlen(dateStr) != 8) { return false; } sscanf(dateStr, "%4d%2d%2d", year, month, day); return true; } // 将年、月、日转换为日期字符串 void formatDate(int year, int month, int day, char* buffer) { sprintf(buffer, "%04d%02d%02d", year, month, day); } int main() { char name[31]; fgets(name, sizeof(name), stdin); name[strcspn(name, "\n")] = '\0'; // 去除换行符 char birthStr[9], deathStr[9]; scanf("%s - %s", birthStr, deathStr); int birthYear, birthMonth, birthDay; int deathYear, deathMonth, deathDay; parseDate(birthStr, &birthYear, &birthMonth, &birthDay); parseDate(deathStr, &deathYear, &deathMonth, &deathDay); char symmetricDates[1000][9]; // 假设最多有1000个对称日 int count = 0; // 遍历所有可能的日期 for (int year = birthYear; year <= deathYear; ++year) { int startMonth = (year == birthYear) ? birthMonth : 1; int endMonth = (year == deathYear) ? deathMonth : 12; for (int month = startMonth; month <= endMonth; ++month) { int startDay = (year == birthYear && month == birthMonth) ? birthDay : 1; int endDay = (year == deathYear && month == deathMonth) ? deathDay : 31; // 临时设置为31,后续会校验 // 根据月份和闰年情况调整最大天数 int maxDay = 31; if (month == 4 || month == 6 || month == 9 || month == 11) { maxDay = 30; } else if (month == 2) { if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { maxDay = 29; } else { maxDay = 28; } } endDay = (endDay > maxDay) ? maxDay : endDay; // 确保endDay不超过该月的最大天数 for (int day = startDay; day <= endDay; ++day) { if (isValidDate(year, month, day)) { char dateStr[9]; formatDate(year, month, day, dateStr); if (isSymmetricDate(dateStr)) { strcpy(symmetricDates[count++], dateStr); } } } } } printf("%s\n", name); for (int i = 0; i < count; ++i) { printf("%s\n", symmetricDates[i]); } return 0; }
上一题 下一题