本篇一共有四道来自牛客网的关于日期计算的题目。
🐶 题1.HJ73 计算日期到天数转换
难度:简单
描述
根据输入的日期,计算是这一年的第几天。
保证年份为4位数且日期合法。
输入描述:
输入一行,每行空格分割,分别是年,月,日
输出描述:
输出是这一年的第几天
示例1
输入:2012 12 31
输出:366
示例2
输入:1982 3 4
输出:63
本题考察日期的转换,难度简单。只需要从1月开始计算即可,需要注意的是闰年的2月有29天
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int main () { int year,mon,day; int data[]={31 ,28 ,31 ,30 ,31 ,30 ,31 ,31 ,30 ,31 ,30 ,31 }; while (cin>>year>>mon>>day) { int sum; for (int i=0 ;i<mon-1 ;i++) { sum=sum+data[i]; } if ((year%400 ==0 ||(year%4 ==0 &&year%100 !=0 ))&&mon>2 ) sum=sum+1 +day; else sum=sum+day; cout<<sum<<endl; } return 0 ; }
🐹 题2.KY222 打印日期
难度:较难
描述
给出年分m和一年中的第n天,算出第n天是几月几号。
输入描述:
输入包括两个整数y(1<=y<=3000),n(1<=n<=366)。
输出描述:
可能有多组测试数据,对于每组数据, 按 yyyy-mm-dd的格式将输入中对应的日期打印出来。
示例1
输入:
2000 3
2000 31
2000 40
2000 60
2000 61
2001 60
输出:
2000-01-03
2000-01-31
2000-02-09
2000-02-29
2000-03-01
2001-03-01
在做日期相关的题目的时候,因为存在闰年与平年的干扰,所以常常考虑将两种年份的月历表分开来存储,然后通过bool返回值的隐式转换来巧取对应的月份。
例如:
1 2 3 4 5 6 7 8 9 int dayofmonth[2 ][13 ]={ {0 ,31 ,28 ,31 ,30 ,31 ,30 ,31 ,31 ,30 ,31 ,30 ,31 }, {0 ,31 ,29 ,31 ,30 ,31 ,30 ,31 ,31 ,30 ,31 ,30 ,31 } }; bool isleapyear (int year) { return (year%4 ==0 &&year%100 !=0 )||(year%400 ==0 ); }
比如我要取1994年的2月份,就可以这样写:
1 dayofmonth[isleapyear (1994 )][2 ];
虽然isleapyear返回的是bool值,但c++支持这种隐式的类型转换
,true则被转为了1,false则转为0。那么如果1994不是闰年,则返回0,也就调用了dayofmonth[0][2]的值,也就是28,同理是闰年则调用下一行的。这种巧用常常出现在日期类的题目中,运用十分灵活。
隐式类型转换在c++编程中还是很常见的。
例如:
这也是一种隐式类型转换,将2转换为A类型,再拷贝给aa2。
再比如:
1 2 void push (const String & str) ;push ("i'm chengzi" );
那么有了以上的铺垫,本题也就很好解决了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int main () { int year,month,day; int number=0 ; while (cin>>year>>number){ month=0 ; int row=isleapyear (year); while (number>dayofmonth[row][month]){ number-=dayofmonth[row][month]; month++; } day=number; printf ("%04d-%02d-%02d\n" ,year,month,day); } return 0 ; }
🐭 题3.KY258日期累加
难度:中等
描述
设计一个程序能计算一个日期加上若干天后是什么日期。
输入描述:
输入第一行表示样例个数m,接下来m行每行四个整数分别表示年月日和累加的天数。
输出描述:
输出m行,每行按yyyy-mm-dd的个数输出。
示例1
输入:
1
2008 2 3 100
输出:
2008-05-13
题3是题2的一种变种,与题2不同的是,题3可以加的数字是可以大于365的。这里我使用的办法是:number只要可以使得day位上的值足够向month位进1则循环,不够则加到day位上借宿循环即可
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 bool isleapyear (int y) { return y % 400 == 0 || (y % 4 == 0 && y % 100 != 0 ); } int print (int year, int month, int day, int number) { int dayofmonth[2 ][13 ] = { {0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 }, {0 , 31 , 29 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 } }; while (number){ if (number>dayofmonth[isleapyear (year)][month]-day+1 ){ number-= dayofmonth[isleapyear (year)][month]-day+1 ; month++; day=1 ; if (month>12 ){ month=1 ; year++; } }else { day+=number; number=0 ; } } printf ("%04d-%02d-%02d\n" , year, month, day); return 0 ; } int main () { int m = 0 ; cin >> m; while (m) { int year, month, day, number; cin >> year >> month >> day >> number; print (year, month, day, number); m--; } }
🐰 题4.KY111 日期差值
难度:中等
描述
有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天
输入描述:
有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD
输出描述:
每组数据输出一行,即日期差值
示例1
输入:
20110412
20110422
输出:
11
这里对于闰年平年的处理也可以采用上文提到的二维数组加bool,但我用的是函数的形式。
同时,题目输入的是年月日所组成的一个数字,所以我们可以考虑将其拆成三部分,这样求取二者差值就容易多了,首先将两个年份相减,再减去多余的月份,加上没考虑的月份即可。比如:20110120与20001230,先将2011与2000相减,得到11年(有闰有平,计算天数时要分开考虑),此时就多了一个1月20天,也少算了一个12月30日,分别加减即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 bool isleapyear (int y) { return y%400 ==0 || (y%4 ==0 && y%100 !=0 ); } int monthDays (int year, int month) { int days[] = {0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 }; if (month == 2 && isleapyear (year)) { return 29 ; } return days[month]; } int getdays (int date1,int date2) { if (date1>date2) swap (date1,date2); int year1=date1/10000 , month1=date1%10000 /100 , day1=date1%100 ; int year2=date2/10000 , month2=date2%10000 /100 , day2=date2%100 ; int days = 0 ; for (int i = year1; i < year2; i++) { days += 365 + isleapyear (i); } for (int i = 1 ; i < month1; i++) { days -= monthDays (year1, i); } days -= day1; for (int i = 1 ; i < month2; i++) { days += monthDays (year2, i); } days += day2; days++; return days; } int main () { int a,b; cin>>a>>b; cout<<getdays (a,b)<<endl; }