題目:
大數學家高斯有個好習慣:無論如何都要記日記。
他的日記有個與衆不同的地方,他從不註明年月日,而是用一個整數代替,比如:4210
後來人們知道,那個整數就是日期,它表示那一天是高斯出生後的第幾天。這或許也是個好習慣,它時時刻刻提醒着主人:日子又過去一天,還有多少時光可以用於浪費呢?
高斯出生於:1777年4月30日。
在高斯發現的一個重要定理的日記上標註着:5343,因此可算出那天是:1791年12月15日。
高斯獲得博士學位的那天日記上標着:8113
請你算出高斯獲得博士學位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21
1,一般解法,將全部天數分爲三個部分
[1]出生日1777-4-30到1777-12-31的天數(已知)
[2]1778-1-1到某年年底的天數,這部分時間成爲完整的年(閏年共366,平年365)
[3]減去以上時間後剩餘天數不足一年,這時計算這一年中的某一天。
#include <iostream>
using namespace std;
int MONTH[] ={0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 0月不存在,2月置0
// 判斷閏年
bool IsLeapyear(int year)
{
if(year % 400==0 || (year%4==0 && year%100!=0)) return true;
else return false;
}
// 月份天數
int Month(int year, int month)
{
int monthDays;
if(month != 2) monthDays = MONTH[month];
else monthDays = IsLeapyear(year) ? 29 : 28;
return monthDays;
}
// 第一部分:某日到年底天數
int DaysToNextYear(int year, int month, int day)
{
int days1 = 0, days2 = 0;
// 某日到年底的天數 = 當日到月尾的天數 + 下月到12月底的天數
days1 = Month(year, month) - day;
for(int i = month+1; i <= 12; i++)
days2 += Month(year, i);
return (days1 + days2);
}
// 第二部分:湊成的完整年的天數
int DaysInFullYear(int sartYear, int nYears)
{
int days = 0;
for(int i = sartYear; i < sartYear+nYears; i++)
{
days += (IsLeapyear(i)?366:365);
}
return days;
}
// 第三部分:求餘下的天數是某一日
int Date(int year, int days)
{
int i;
for(i = 1; i <= 12; i++)
{
if (days > Month(year, i)){
days -= Month(year, i);
}
else break;
}
cout<<"Time: "<<year<<"-"<<i<<"-"<<days<<endl;
}
int main(void)
{
// part1
int allDays = 5343, days1, days2;
int year = 1777, month = 4, day = 30;
days1 = DaysToNextYear(year, month, day);
days2 = DaysInFullYear(year+1, (allDays-days1)/365);
Date(year + 1 + (allDays-days1)/365, allDays - days1 - days2);
return 0;
}
輸出結果爲
與樣例多了一天,題意是將出生日爲第一天,即應該減去一天。
修改程序後,本題的正確結果爲:
注意提交格式。
2, 解法2,求兩個日期的間隔天數。
已知1777-4-30到某年某月某日的天數爲8113,可以求 1777-4-30到特定的年月日的天數,不斷改變後一個日期以使j間隔天數到達8113即可,實際是求兩個日期間隔的天數,如: 求 1777-4-30到1791-12-15相隔的天數。採用的是後一個日期減去前一個日期的想法。
1777其實不滿一年,它只有3個月+30天,使用 1791年的12月15日(其實是11個月+15日)減去這部分時間麼?防止後一個日期不足一年的時間小於前一個日期不足一年的時間,最好從1791以前挪用一年的時間+1791不足一年的時間-前一個日期1777不足一年的時間。
[1]1790整年的時間+12月15日(1791年) - 4月30日(1777年)
[2]再用1789年 - 1777年,就是 1777到 1789的時間。
以上[1][2]部分時間相加後即爲所求的日期相隔時間。
#include <iostream>
using namespace std;
int MONTH[] ={0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 0月不存在,2月置0
// 判斷閏年
bool IsLeapYear(int year)
{
if(year % 400==0 || (year%4==0 && year%100!=0)) return true;
else return false;
}
// 某年的天數
int DaysYear(int year)
{
if(IsLeapYear(year)) return 366;
else return 365;
}
// 某年月初(1月1日)到某月某日的天數
int DaysDate(int year, int month, int day)
{
int days = 0;
// 先計算該月前的天數
for(int i = 1; i <= month-1; i++)
days += MONTH[i];
// 另外計算2月
if(IsLeapYear(year)) days+=29;
else days+=28;
// 加上該月的天數
days += day;
return days;
}
int main(void)
{
int preYear = 1777, preMonth = 4, preDay = 30;
//int curYear = 1791, curMonth = 12, curDay = 15;
int curYear = 1799, curMonth = 7, curDay = 15;
int days1 = 0, days2 = 0, days3 = 0, days4 = 0;
// 1790整年時間
days1 = DaysYear(curYear-1);
// 1791年的天數, 11個月+30天
days2 = DaysDate(curYear, curMonth, curDay);
// 1 1790整年的時間+12月15日(1791年) - 4月30日(1777年)
days3 = days1 + days2 - DaysDate(curYear, preMonth, preDay);
// 2 1789年(12月31日) - 1777年(1月1日), 也等於1777年到1789年的天數
for(int i = preYear; i<=curYear-2; i++)
days4 += DaysDate(i, 12, MONTH[12]);
// 兩個年月日之間的天數
cout<< days3 + days4<<endl;
}
輸出結果:是的,與樣例依然相差了一天,應該將出生了那天計算在內。
這時與所求仍然有距離,題已知的是距離所知日期的天數:8113
看到 8113 - 5343 = 2770; 大約相差7年,更改日期的年數
int curYear = 1798, curMonth = 12, curDay = 15;
輸出:
8113 - 7899相差了214天,由於已經是12月,必須增加年數。
int curYear = 1799, curMonth = 12, curDay = 15;
輸出:
8264 - 8113多了 151天,差不多5個月,於是再次更改
int curYear = 1799, curMonth = 7, curDay = 15;
輸出:
結果少了2天,
再次更改:
int curYear = 1799, curMonth = 7, curDay = 17;
輸出:
嘗試終得結果,但是莫忘用例中必須加上出生那天,所以我們的結果應該是8112,最終的答案是:
1799-7-16
注意提交格式
3,在解法2的的基礎上,兩個日期間隔相當於在數軸上的兩個非負數的點A,B,可以簡單的用B-A等於之間相隔的距離。某個日期在軸上的位置,如1791-12-15:0年1月1日(元年0開始還是1開始?這不重要)到1790年12月31日 + 11月30天(1791)
int main(void)
{
int preYear = 1777, preMonth = 4, preDay = 30;
int curYear = 1791, curMonth = 12, curDay = 15;
int days1 = 0, days2 = 0, days3 = 0;
// 元年是0年還是1年呢,這不重要
// 1 0年 - 1777年 + 4月30在這年的時間
for(int i = 0; i <= preYear-1; i++) days1 += DaysYear(i);
days1 += DaysDate(preYear, preMonth, preDay);
// 2 0年 - 1791年 + 12月15在這年的時間
for(int i = 0; i <= curYear-1; i++) days2 += DaysYear(i);
days2 += DaysDate(curYear, curMonth, curDay);
cout<<days2 - days1<<endl;
return 0;
}
輸出:哈,答案正確。