【每日一题】美国节日(基姆拉尔森公式、蔡勒公式)
相关文章:
1、题目来源
牛客网:美国节日
2、题目描述
和中国的节日不同,美国的节假日通常是选择某个月的第几个星期几这种形式,因此每一年的放假日期都不相同。具体规则如下:
-
1月1日:元旦
-
1月的第三个星期一:马丁·路德·金纪念日
-
2月的第三个星期一:总统节
-
5月的最后一个星期一:阵亡将士纪念日
-
7月4日:美国国庆
-
9月的第一个星期一:劳动节
-
11月的第四个星期四:感恩节
-
12月25日:圣诞节
现在给出一个年份,请你帮忙生成当年节日的日期。
3、输入/出描述
输入描述:
输入包含多组数据,每组数据包含一个正整数year(2000≤year≤9999)。
输出描述:
对应每一组数据,以“YYYY-MM-DD”格式输出当年所有的节日日期,每个日期占一行。每组数据之后输出一个空行作为分隔。
4、示例
输入:
2014
2013
输出:
2014-01-01
2014-01-20
2014-02-17
2014-05-26
2014-07-04
2014-09-01
2014-11-27
2014-12-25
2013-01-01
2013-01-21
2013-02-18
2013-05-27
2013-07-04
2013-09-02
2013-11-28
2013-12-25
5、解题思路
这道题的难点是:判断某个月的1号是星期几。
对于问题一常用的两个公式是基姆拉尔森公式和蔡勒公式
● 基姆拉尔森公式: w = ( d + 2 × m + 3 × ( m + 1 ) 5 + y + y 4 − y 100 + y 100 + 1 ) m o d 7 w=(d + 2\times m + \frac{3\times(m+1)}{5} + y + \frac{y}{4} - \frac{y}{100} + \frac{y}{100} +1) mod 7 w=(d+2×m+53×(m+1)+y+4y−100y+100y+1)mod7
● 蔡勒公式: w = ( y + [ y 4 ] + [ c 4 ] − 2 c + [ 13 × ( m + 1 ) 5 ] + d − 1 ) m o d 7 w=(y + [\frac{y}{4}] + [\frac{c}{4}] -2c + [\frac{13\times(m+1)}{5}] + d -1) mod 7 w=(y+[4y]+[4c]−2c+[513×(m+1)]+d−1)mod7
其中
w: 星期(计算所得的数值对应的星期:0-星期日;1-星期一;2-星期二;3-星期三;4-星期四;5-星期五;6-星期六)
c: 是世纪数减一,也就是年份前两位数,即y/100
y: 是这和世纪的第几年,即y%100
m: 月(m的取值范围为3至14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算)
d: 日
[ ]: 作高斯符号,代表向下取整,即,取不大于原数的最大整数。
mod: 取余
推荐文章:
【蔡勒公式】
6、代码展示
#include<iostream>
using namespace std;
//输入某年某月第几个星期几,正数还是倒数,输出几号
int WeekDay(int y,int m,int c,int w,bool B)
{
int day,week,i=0;
if(m == 1 || m == 2) //将1、2月当作上一年的13、14月来计算
{
m += 12;
y--;
}
for( day = B?1:31; day <= B?31:1; B?(day++):(day--) )
{
week=(day + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400)%7;//基姆拉尔森公式
if(week+1==w) ++i;
if(i==c) break;
}
return day;
}
int main(void)
{
int year;
while(cin>>year)
{
cout<<year<<"-01-01"<<endl; //元旦
//WeekDay(年,月,第几个星期,星期几,正数1倒数0)
printf("%d-01-%02d\n",year,WeekDay(year,1,3,1,1));
printf("%d-02-%02d\n",year,WeekDay(year,2,3,1,1));
printf("%d-05-%02d\n",year,WeekDay(year,5,1,1,0));
cout<<year<<"-07-04"<<endl;
printf("%d-09-%02d\n",year,WeekDay(year,9,1,1,1));
printf("%d-11-%02d\n",year,WeekDay(year,11,4,4,1));
cout<<year<<"-12-25"<<endl<<endl;
}
return 0;
}