【hihoCoder】1148:2月29日
问题:http://hihocoder.com/problemset/problem/1148
给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期)。
思路:
1. 将问题转换成求两个日期间有几个闰年
- 基本公式:闰年数(endYear,startYear) = 闰年数(0, endYear) - 闰年数(0, startYear)
- 注意点:区间的端点值
2. 闰年的要求
- 不能被100整除,能被4整除
- 或能被400整除
3. cnt = [i / 4]
- 对cnt = [i / 4]取整: 这个可以得出从0到i中有几个数是4的倍数 1*4, 2*4, 3*4, 4*4......
- 同理,可以求得有几个是100的倍数,几个是400的倍数
4. 关于两端,就是startYear和endYear是否应该再计算在内的问题
- 1到10之间有 10 -1 + 1 = 10 个数
- 所以应该注意区间的第一个数!直接减的话,会将它减掉了
5. 代码注意点
- 用scanf()来读入有一定格式的输入,string类型不用来存字符串的。
1 string str; 2 scanf("%s", str);//不应该这么用 3 char strs[10]; 4 scanf("%s", strs);
- scanf()需要包含头文件 #include <string.h>
代码:
1 #include <iostream> 2 #include <string.h> 3 using namespace std; 4 5 bool isLeap(int year) 6 { 7 if ((year % 100 != 0 && year % 4 == 0) || (year % 100 == 0 && year % 400 == 0)) 8 return true; 9 return false; 10 } 11 12 int main() 13 { 14 int cnt, startDay, endDay, startYear, endYear, leapCnt, i = 0; 15 char startMonth[20], endMonth[20]; 16 17 cin >> cnt; 18 while (i++ < cnt) 19 { 20 leapCnt = 0; 21 scanf("%s %d, %d", startMonth, &startDay, &startYear); 22 scanf("%s %d, %d", endMonth, &endDay, &endYear); 23 24 //日期已经超过2月29日,则不应该再考虑startYear里面的2月29日 25 if ((strcmp(startMonth, "February") != 0 && strcmp(startMonth, "January") != 0) 26 || (strcmp(startMonth, "February") == 0 && startDay > 29)) 27 startYear++; 28 //日期没有超过2月29日,则不应该再考虑endYear里面的2月29日 29 if (strcmp(endMonth, "January") == 0 30 || (strcmp(endMonth, "February") == 0 && endDay < 29)) 31 endYear--; 32 leapCnt = (endYear / 4 - endYear / 100 + endYear / 400) - (startYear / 4 - startYear / 100 + startYear / 400); 33 if (isLeap(startYear))//startYear里面的2月29日! 34 leapCnt++; 35 cout << "Case #" << i << ": " << leapCnt << endl; 36 } 37 return 0; 38 }