UVa 150 Double Time

📅 发布时间:2026/7/5 11:24:49 👁️ 浏览次数:
UVa 150 Double Time
题目描述儒略·恺撒于公元前45 4545年采用了一种标准历法每年365 365365天每四年增加一天2 22月29 2929日。但这一历法并不完全准确季节的开始时间在一年中逐渐偏移。1582 15821582年教皇格里高利十三世颁布了一种新历法格里高利历规定世纪年只有能被400 400400整除才是闰年。同时为了将历法与季节重新对齐当年进行了一次调整1582 15821582年10 1010月4 44日星期四之后直接是10 1010月15 1515日星期五。天主教国家立即采用了这一新历法而英国和美国直到1752 17521752年才改用1752 17521752年9 99月2 22日星期三之后是9 99月14 1414日星期四。因此有一段很长的时期历史记录使用了两种不同的历法。本题要求编写程序读入一个日期判断它是旧式儒略历还是新式格里高利历并将其转换为另一种历法的日期。输入格式输入由多行组成每行包含一个星期 日期 月份 年份的格式例如Friday 25 December 1992。日期范围在1600 16001600年1 11月1 11日至2099 20992099年12 1212月31 3131日之间但转换后的日期可能超出此范围。所有星期和月份的名称首字母大写其余小写。输入以一行仅包含#的行结束。输出格式输出对应于输入的每一行输出转换后的日期格式与输入相同但旧式日期在日期数字后紧跟一个星号*中间无空格。样例输入Saturday 29 August 1992 Saturday 16 August 1992 Wednesday 19 December 1991 Monday 1 January 1900 #样例输出Saturday 16* August 1992 Saturday 29 August 1992 Wednesday 1 January 1992 Monday 20* December 1899题目分析本题的核心在于历法转换与星期匹配。我们需要判断一个给定的日期带有星期信息是属于儒略历还是格里高利历然后将其转换为另一种历法下的日期并保持星期一致。关键点闰年规则不同儒略历年份能被4 44整除即为闰年。格里高利历年份能被400 400400整除或能被4 44整除但不能被100 100100整除。日期调整1582 15821582年10 1010月4 44日儒略历之后直接跳到10 1010月15 1515日格里高利历。1752 17521752年9 99月2 22日儒略历之后直接跳到9 99月14 1414日格里高利历。星期匹配输入中给出了星期我们可以利用星期信息来判断该日期原本属于哪种历法。如果日期在儒略历下计算出的星期与给定星期一致则它是旧式日期否则是新式日期。解题思路统一基准日期选择一个共同的基准日期例如1583 15831583年1 11月1 11日计算给定日期距离该基准的天数。分别按照儒略历和格里高利历的规则计算天数。判断历法类型根据基准日期的星期已知为星期一分别计算出两种历法下给定日期对应的星期。如果与输入星期一致则该日期属于该历法。进行转换如果日期是儒略历则将其转换为格里高利历反之亦然。转换时根据两种历法的天数差调整日期。输出格式输出转换后的日期如果是旧式儒略历则在日期后加*。算法步骤读入一行日期解析星期、日、月、年。计算该日期在儒略历和格里高利历下距离基准日期的天数。根据星期匹配判断原历法。根据原历法使用另一种历法的规则重新计算日期。输出转换结果旧式日期后加*。代码实现// Double Time// UVa ID: 150// Verdict: Accepted// Submission Date: 2016-01-30// UVa Run Time: 0.019s//// 版权所有C2016邱秋。metaphysis # yeah dot net#includebits/stdc.husingnamespacestd;structdate{intdayOfWeek,dayOfMonth,month,year;boolisOldFormat;};conststring months[12]{January,February,March,April,May,June,July,August,September,October,November,December};conststring weekdays[7]{Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday};constintdaysInMonth[2][12]{{31,28,31,30,31,30,31,31,30,31,30,31},{31,29,31,30,31,30,31,31,30,31,30,31}};intisLeapYear(intyear,booluseOldFormat){return(useOldFormat?year%40:(year%4000||(year%40year%100!0)))?1:0;}voidaddDays(datestartDate,intdays,booluseOldFormat){while(days0){intleapYearisLeapYear(startDate.year,useOldFormat);// 注意判断条件if(leapYeardays366){days-366;startDate.year1;}elseif(!leapYeardays365){days-365;startDate.year1;}else{for(inti0;i12;i)if(daysdaysInMonth[leapYear][i]){days-daysInMonth[leapYear][i];startDate.month1;}elsebreak;startDate.dayOfMonthdays;days0;}}}intgetDays(date aDate,booluseOldFormat){intdaysuseOldFormat?88:78;for(inti1583;iaDate.year;i)days(isLeapYear(i,useOldFormat)?366:365);for(inti0;iaDate.month;i)daysdaysInMonth[isLeapYear(aDate.year,useOldFormat)][i];daysaDate.dayOfMonth;returndays;}voidconvertToOtherDate(date aDate){// 计算新旧两种日期格式两个日期之间的相隔天数分别从旧的基准日期和// 新的基准日期计算间隔天数统一调整为从 1583-01-01 开始计算天数。intoldDaysgetDays(aDate,true);intnewDaysgetDays(aDate,false);// 根据星期几是否吻合来判断日期格式并转换aDate.dayOfMonth0;aDate.month0;aDate.year1583;aDate.isOldFormat(3oldDays)%7aDate.dayOfWeek;if(aDate.isOldFormat){aDate.dayOfWeek(3oldDays)%7;oldDays-78;addDays(aDate,oldDays,false);}else{aDate.dayOfWeek(3newDays)%7;newDays-88;addDays(aDate,newDays,true);}aDate.isOldFormat!aDate.isOldFormat;coutweekdays[aDate.dayOfWeek] aDate.dayOfMonth;if(aDate.isOldFormat)cout*;cout months[aDate.month] aDate.year\n;}intmain(){cin.tie(0);cout.sync_with_stdio(false);string weekDayText,monthText;date aDate;while(cinweekDayText,weekDayText!#){cinaDate.dayOfMonthmonthTextaDate.year;aDate.dayOfWeekfind(weekdays,weekdays7,weekDayText)-weekdays;aDate.monthfind(months,months12,monthText)-months;convertToOtherDate(aDate);}return0;}总结本题通过历法转换与星期匹配考查了对日期处理的基本能力。关键在于理解两种历法的闰年规则和历史上的日期调整以及如何通过星期信息判断原历法类型。算法上我们采用统一的基准日期分别计算天数再根据星期匹配进行转换。代码中注意处理闰年和月份天数确保转换的准确性。