PAT乙级(Basic Level)练习题 不吉利的日期

题目描述
在国外,每月的 13 号和每周的星期 5 都是不吉利的。特别是当 13 号那天恰好是星期 5时,更不吉利。
现在给你一个年份,请你从小到大依次输出当年所有13 号是星期 5 的月份。

输入描述:
输入包含多组数据,每组数据包含一个正整数year(2000≤year≤9999)。

输出描述:
对应每一组数据,输出所有符合条件的月份,月份之间用空格隔开。
如果当年不存在13号是星期五的月份,就输出一行Luck。

输入例子:

2000
2001
2002

输出例子:

10
4 7
9 12

\color{blue}解题思路:
这道题并不复杂,但是在细节控制方面有点繁琐。

我们要解决的问题是计算当年每个月的13号是星期几,年份输入的范围是2000≤year≤9999,直接求解可能比较难,我们一步一步逼近。

首先我们需要计算出输入年份的1月1日是星期几week,我们查找网络知2000年1月1日星期六

平年一年365天(52周+1天),闰年一年366天(52周+2天)。
也就是说平年一年过去后week = (week + 1) % 7,闰年一年过去后week = (week + 2) % 7,实际效果是闰年 = 平年 + 1

因此我们需要计算[2000, yea)中有多少个闰年
[2000, yea)期间总共有year - 2000年,闰年数量为(year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400

注意: 我们这里把2000年单独拿出来,因为当year == 2000时,2000年的闰年并不会影响2000年1月1号的计算。

因此year年1月1日星期几week求解计算过程为

int week = 6;//2000年1月1日 星期六,注意星期日用0表示
//计算该年1月1日星期几,平年365天(52周+1天)闰年366(52周+2天),也就是平年增加一天,闰年增加两天
//期间year - 2000年,(year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400 个闰年
week = (week + (year - 2000) + (year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400) % 7;
if (year > 2000) {
    //2000年也是l闰年,但是单独算,因为当year == 2000时,此时它虽是闰年,但是不影响2000年1月1日是星期几的计算
    week += 1;
}

知道了year年1月1日是星期几,记为week0,那么

year年112日 week1 = (week0 + 12) % 7
year年212日 week2 = (week0 + 31 + 12) % 7  注:131天
year年312日 week3 = (week0 + 31 + 28 or 29 + 12) % 7  注:平年 228天,闰年 229天
year年412日 week4 = (week0 + 31 + 28 or 29 + 31 + 12) % 7  注:331...

\color{blue}代码实现:

#include <iostream>
using namespace std;

int main() {
    int resTable[12] = {0}, year = 0;
    //resTable存放当年13号为星期5的月份,monthDays[month]记录month月的天数,其中2月根据year是否为闰年动态调整
    int monthDays[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    //scanf函数范围值为正确获取到数据的参数个数,当没有输入返回-1
    while (scanf("%d", &year) != -1){
        //2000年1月1日 星期六,注意星期日用0表示,count记录13 号是星期 5 的月份个数
        int week = 6, count = 0;
        //计算该年1月1日星期几,平年365天(52周+1天)闰年366(52周+2天),也就是平年增加一天,闰年增加两天
        //期间year - 2000年,(year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400 个闰年
        week = (week + (year - 2000) + (year - 2001) / 4 - (year - 2001) / 100 + (year - 2001) / 400) % 7;
        if (year > 2000) {
            //2000年也是l闰年,但是单独算,因为当year == 2000时,此时它虽是闰年,但是不影响2000年1月1日是星期几的计算
            week += 1;
        }
        //如果当年是闰年,则二月有29天
        if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
            monthDays[2] = 29;
        } else {
            monthDays[2] = 28;
        }
        //判断当年的每个月13号是不是星期5
        for (int month = 1; month < 13; ++month) {
            if ((week + 12) % 7 == 5) {
                //如果是就记录掉resTable中,count记录13 号是星期 5 的月份个数
                resTable[count++] = month;
            }
            //转到下个月的1号
            week += monthDays[month];
        }
        for (int i = 0; i < count - 1; ++i) {
            printf("%d ", resTable[i]);
        }
        printf("%d\n", resTable[count - 1]);
    }
    return 0;
}

在这里插入图片描述

发布了1010 篇原创文章 · 获赞 273 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/104717957
今日推荐