[蓝桥杯][算法训练VIP]黑色星期五(基姆拉尔森计算公式)

[蓝桥杯][算法训练VIP]黑色星期五(基姆拉尔森计算公式)

黑色星期五

题目描述

有些西方人比较迷信,如果某个月的13号正好是星期五,他们就会觉得不太吉利,用古人的说法,就是“诸事不宜”。请你编写一个程序,统计出在某个特定的年份中,出现了多少次既是13号又是星期五的情形,以帮助你的迷信朋友解决难题。

说明:(1)一年有365天,闰年有366天,所谓闰年,即能被4整除且不能被100整除的年份,或是既能被100整除也能被400整除的年份;(2)已知1998年1月1日是星期四,用户输入的年份肯定大于或等于1998年。

输入

输入只有一行,即某个特定的年份(大于或等于1998年)。

输出

输出只有一行,即在这一年中,出现了多少次既是13号又是星期五的情形

样例输入

1998

样例输出

3

分析

方法一 :暴力法

第一种方法是用正常的思路,判断这一年每月13号是否为星期五,那么怎么才能判断这一天是星期五呢,我们知道,1月1日是星期四,那么1月2日就是星期五,以后每隔七天又是星期五。因此如果天数对7求余等于2,那么这一天就是星期五。

那么又有一个问题了?我们怎样求天数。比如,2020年2月13日距1998年1月1日有多少天,只要求出天数,这个问题就解决了。我们可以直接暴力解决,用for循环将每一年的天数相加,注意不要加上你所求的这一年,因为我们就是要统计这一年黑色星期五的次数。

#include

int main (void){

int year;

scanf("%d",&year);

int i,j;

int tab[2][13]={

{0,31,28,31,30,31,30,31,31,30,31,30,31},//非闰年

{0,31,29,31,30,31,30,31,31,30,31,30,31},//闰年

};

int day=0,flag;

for(i=1998;i

flag=((i%4==0&&i%100!=0) || (i%400==0));//判断闰年

if(flag){

day+=366;

}

else{//计算所求年之前所有的天数

day+=365;

}

}

flag=((year%4==0&&year%100!=0) || (i%400==0));//判断所求这一年是否为闰年

int count=0;

for(i=1;i<13;i++){

day+=tab[flag][i-1];//加上上一月的天数

if((day+13)%7==2){//判断是否为黑色星期五

count++;

}

}

printf("%d",count);

return 0;

}

方法二 :基姆拉尔森计算公式

week=(d+2m+3(m+1)/5+y+y/4-y/100+y/400+1)%7;

可以直接计算一个日期是星期几,这样就方便多了。

在公式中d表示日期中的日数,m表示月份数,y表示年数。 注意:在公式中有个与其他公式不同的地方: 把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。

此公式的推导此处不详细解释,读者如感兴趣,可自行百度。

百度百科中关于基姆拉尔森计算公式的介绍

知道了这个公式后,此题是不是变得更简单了呢?话不多说,代码如下。

参考代码

#include

int main (void){

int d=13,m,y,year;

scanf("%d",&year);

int i,count=0,week;

for(i=1;i<=12;i++){

y=year;

m=i;

if(m==1||m==2){//一月二月时月份与年份都会发生变化

m+=12;//因此定义两个新变量y,m

y--;

}

week=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;

if(week==5){

count++;

}

}

printf("%d",count);

return 0;

}

如有错误之处,敬请指正!!!

相关推荐

Instagram 忘记密码无法登入,如何重设密码取回帐号
365体育投注官网

Instagram 忘记密码无法登入,如何重设密码取回帐号

📅 09-14 👁️ 4496
在屋里放一碗糖水真的能驱蚊吗?
365bet体育在线比分

在屋里放一碗糖水真的能驱蚊吗?

📅 08-24 👁️ 1717
在屋里放一碗糖水真的能驱蚊吗?
365bet体育在线比分

在屋里放一碗糖水真的能驱蚊吗?

📅 08-24 👁️ 1717