P8651 [蓝桥杯 2017 省 B] 日期问题 题解

· · 题解

分析

本题的年份已经给定了范围,所以直接枚举即可,不会超时

思路

使用三重循环,第一层循环枚举年份,第二层循环枚举月份,第三层循环枚举天数。

可以使用一个数组来记录每个月的天数,不用逐个月来判断。

口诀:一三五七八十腊,三十一天永不差,四六九冬三十日,平年二月二十八,闰年二月把一加。

那么如何判断一个年份是否是闰年呢?一个年份是闰年,当且仅当它满足以下两种条件之一:

  1. 年份是 4 的倍数但不是 100 的倍数。

  2. 年份是 400 的倍数。

判断闰年的代码很简单,只需要进行基本逻辑上面的判断即可:

inline bool isLeapYear(int y) {
    return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}

题目中说,格式有三种可能,所以我们要判断这三种情况。

  1. 『年月日』的格式:
a == year % 100 && b == month && c == day
  1. 『月日年』的格式:
a == month && b == day && c == year % 100
  1. 『日月年』的格式:
a == day && b == month && c == year % 100

注意,由于输入的年份只有两位,判断时要把枚举出来的年份对 100 取模,这样就可以得到它的后两位,可以进行比较了。

输出格式也要非常注意:月和日前要补零

printf("%d-%02d-%02d\n", year, month, day);

代码

#include <bits/stdc++.h>
using namespace std;

const int StartYear = 1960, EndYear = 2059;

/*
一三五七八十腊,
三十一天永不差,
四六九冬三十日,
平年二月二十八,
闰年二月把一加。
*/
int daysOfMonth[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};        

// 判断是否为闰年
inline bool isLeapYear(int y) {
    return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}

int main() {
    int a, b, c;
    scanf("%d/%d/%d", &a, &b, &c);
    for(int year = StartYear; year <= EndYear; ++year) { // 1960年到2059年
        daysOfMonth[2] = (isLeapYear(year) ? 29 : 28);  // 根据是否是闰年来修改二月的天数
        for(int month = 1; month <= 12; ++month)
            for(int day = 1; day <= daysOfMonth[month]; ++day)
                if((a == year % 100 && b == month && c == day) ||
                   (a == month && b == day && c == year % 100) ||
                   (a == day && b == month && c == year % 100))  // 判断是否符合条件
                    printf("%d-%02d-%02d\n", year, month, day); // 注意输出的格式
    }
    return 0;
}

题解结束了,有什么问题欢迎私信交流,谢谢大家!