题目:高斯日记
大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费 呢?
高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。
高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21
分析:初步判断为日期加减的问题,需要考虑的是:1.是否闰年,2.每月的日期。
从解题方向上来看,就是简单的枚举。
所以,总共有三种求解方法,一是手算,二是借助Excel计算,三是编程,下面具体介绍excel和编程方法
计算依据:公历年份是4的倍数的,一般都是闰年。但公历年份是整百数的,必须是400的倍数才是闰年。
要判断某一年是不是闰年,一般方法是用4或400去除这一年的年份数,如果除得的商是整数而没有余数,那么这一年是闰年;如果有余数,那么这一年是平年。
法一:excel解法
step1:列出高斯出生时1777年当年的日期情况,B列为月份,C列为月份对应的日期。
至于4月30日为什么是第一天,在后面对于5343是1791年12月15日的验算中会得到证明。
step2:从1778年开始按年份依次列出,在D列中用公式计算年份除以4后的结果来判断是否闰年,之后下拖;
随后根据是否闰年的计算结果,依次写出每年的天数。
step3:下面就是正常的逻辑计算了,因过程简单,所以直接附上截图
如图所示,最后结果为:1779-07-16(注意题目所要求的格式)
法二:编程法
整体思路:枚举,不停地加,直到符合条件时才进行相应的运算,运算后继续加。
代码中共5条if语句,分别对应着跨年、两种情况跨月、两种情况跨二月。
#include<iostream>
using namespace std;
bool isleapyear(int y)//闰年的判定方法
{
return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0);
}
int main(int argc,const char *argv[])
{
int y=1777; //年
int m=4; //月
int d=30; //日
for (int i = 0;i < 8112;++i)//注意只需要数8112次
{
d++; //不停地加,通过下面的if语句暴力得出结果
if (m == 12 && d == 32)//跨年时日历的翻越
{
y++;
m = 1;
d = 1;
continue;
}
if ((m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10)&&d==32)
{//含31天的月份的翻越,12月的前面已经写了
m++;
d = 1;
continue;
}
if ((m == 4 || m == 6 || m == 9 || m == 11 )&&d==31)
{//含30天的月份的翻越
m++;
d = 1;
continue;
}
if (m == 2 && isleapyear(y) && d==30)
{
m++;
d = 1;
continue;
}
if (m == 2 && !isleapyear(y) && d == 29)
{
m++;
d = 1;
continue;
}
}
cout << y << "-" << m << "-" << d;
return 0;
}
验算时,将for循环中的“8112”改成“5344”,看结果是否是1791-12-15