题目描述
在国外,每月的 13 号和每周的星期 5 都是不吉利的。特别是当 13 号那天恰好是星期 5时,更不吉利。
现在给你一个年份,请你从小到大依次输出当年所有13 号是星期 5 的月份。
输入描述:
输入包含多组数据,每组数据包含一个正整数year(2000≤year≤9999)。
输出描述:
对应每一组数据,输出所有符合条件的月份,月份之间用空格隔开。
如果当年不存在13号是星期五的月份,就输出一行Luck。
输入例子:
2000
2001
2002
输出例子:
10
4 7
9 12
这道题并不复杂,但是在细节控制方面有点繁琐。
我们要解决的问题是计算当年每个月的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年1月12日 week1 = (week0 + 12) % 7
year年2月12日 week2 = (week0 + 31 + 12) % 7 注:1月31天
year年3月12日 week3 = (week0 + 31 + 28 or 29 + 12) % 7 注:平年 2月 28天,闰年 2月 29天
year年4月12日 week4 = (week0 + 31 + 28 or 29 + 31 + 12) % 7 注:3月 31天
...
#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;
}