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;
}
上一题
下一题