题目链接
题目大意
输入一个日期:YYYY-MM-DD
求接下来最近的哪一年里的同一个日子,和今天的星期数一样。
分析
应用Zeller公式,可以计算1582年10月4日后任一日期的星期。
解决了这个问题后,只需枚举之后的每一年的同一日期,找到最近的星期数相同的即可。
但这道题这样解的话要注意一个坑点,如果输入的日期为闰年的2月29号,不能直接+1枚举以后的年份,因为平年根本就没有2月29号,因此可以加4枚举。但+4也不一定是闰年,因此每次再判断一下枚举的年份是否为闰年。我因为这些原因WA了两次 QAQ
所以做日历题一定要特别小心闰年这个存在啊!!!
代码
#include <bits/stdc++.h>
using namespace std;
const double pi=4*atan(1.0);
bool is_reapyear(int y)
{
if (((y%4==0)&&(y%100!=0))||(y%400==0))
return true;
else
return false;
}
int Zeller(int year,int month,int day)///蔡勒公式算星期
{
if (month==1||month==2)
{
year--;
month+=12;
}
int c=year/100;
int y=year-c*100;
int week=(c/4)-2*c+(y+y/4)+(13*(month+1)/5)+day-1;
while(week<0){week+=7;}
week%=7;
return week;
}
int main()
{
int year,month,day,T;
char ch[15];
scanf("%d",&T);
while (T--)
{
scanf("%s",ch);
year=(ch[0]-48)*1000+(ch[1]-48)*100+(ch[2]-48)*10+(ch[3]-48);
month=(ch[5]-48)*10+(ch[6]-48);
day=(ch[8]-48)*10+(ch[9]-48);
int week=Zeller(year,month,day);
int week2;
if (month==2&&day==29)///如果输入为闰年的2月29号
{
for (int i=year+4;i<=9999;i+=4)//每四年枚举
{
if (!is_reapyear(i)) continue;//不是闰年就PASS
week2=Zeller(i,month,day);
if (week==week2)
{
printf("%d\n",i);
break;
}
}
}
else
{
for (int i=year+1;i<=9999;i++)
{
week2=Zeller(i,month,day);
if (week==week2)
{
printf("%d\n",i);
break;
}
}
}
}
return 0;
}