杭电 1308 What Day Is It?

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1308


求日期的题目,没什么难度,但是特别需要注意细节。

在Discuss中有讨论,提到了关于日期的计算:

1/1/1是星期日

1582年之前,只要能被4整除就是闰年

1582之后,就是按照现在的规则是闰年

1582年10月4日之后就是1582年10月15日,5号到14号是没有的

去掉这些天时为了补偿回之前错误的闰年规则所多算的天数

1752年9月2号之后就是1752年9月14号,3号到13号是没有的


当然这些都属于历史原因了,一步一步可以计算模拟,但是需要考虑太多的东西,之前做这些题目都是一个一个算,后来发现有公式可以计算:

计算出当前日期到公元1年1月1日的总天数,而那一天刚好是周一(网上也有说是周日的,但是根据周一可以AC)

int GetWeek(int year, int mon,  int day)
{
    int ret=(year-1)*365+(year-1)/4-(year-1)/100+(year-1)/400,i;   //计算到公元1年1月1日
    for(i=0;i<mon-1;ret+=date[leapyear(year)][i++]);  //把当前的几个月的天数加上,
    return (ret+day)%7;//将这个月的天数加上。
}


计算的时候需要对1582特殊对待:(但是由于题目说的是大英帝国,大英帝国是在1752年才开始修改历法的,所以做得时候其实是对1752判断。但是仅仅是推迟了而已,多出来的11天对我们的计算并不影响)

bool check(int y,int m,int d)
{
 if(y<=0)
  return false;
 if(m<1 || m>12)
  return false;
 if(!(d>=0 && d<=date[leapyear(y)][m-1]))
  return false;
 if(y==1752 && m==9 && (d>2 && d<14))
  return false;
 return true;
}

计算的时候区别对待,1752的9月2号之前需要添加中断的11天。

计算如下:

if(check(y,m,d))
{
	if(y<1752 || (y==1752 && m<9) || (y==1752 && m==9 && d<=2))
		printf("%s %d, %d is a %s\n",month[m-1],d,y,s[g(y,m,d+11)]);
	else
		printf("%s %d, %d is a %s\n",month[m-1],d,y,s[g(y,m,d)]);
}
其他的就不粘了。

为什要添加这中断的11天呢,因为1752个年头其实只要是1752%4==0,就是闰年,而我们上边计算的时候,是按照现在的算法计算,而之后的闰年则是现在的算法,计算天数的时候已经把这中断的11天加上了。

好了,就这么多了。


 
 


你可能感兴趣的:(it,杭电,day,what,is,1308)