HDU - 1201 - 18岁生日
https://vjudge.net/problem/HD...
一句话题意:给定出生日期(格式为
1988-03-07
),求到18岁生日为止经历了多少天;没有18岁生日输出-1。
这个题目太普通了,类似的问题可能满大街都是。这不是一个算法竞赛等级的题目,但是还是有的好说。我要记录的是我做这题的思考方式。
解:
首先考虑闰年。一般来说,公元闰年的确定方法如下:年份若为400的正整倍数
时,闰;否则,年份是4的正整倍数
且不是100的正整倍数
时,闰;都不符合,平。这点体现在函数is_leap
里。
我发现,若今年是闰年,日期在2月29日之前或之后的两种情形到“明年今日”的天数是不同的。如2008-03-01
到2009-03-01
经历366
天,2008-02-28
到2009-02-28
经历365
天。
对称地,若今年是平年,明年是闰年也有类似的规律可说。
这就是我要记录的“局部分离思想”。这个问题一开始看很复杂,但是我们发现,这一年到下一年,无非只有3种大情形。日期在2月29日之前简记为“前”;日期在这之后(含)简记为“后”。列表如下。
平=>平
前365天;后365天平=>闰
前365天;后366天闰=>平
前366天;后365天
这样一来,问题就迎刃而解了。
代码如下。
//AC,0ms;
#ifdef LOCAL
#include<ctime>
#endif
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<sstream>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#define LL long long
using namespace std;
int is_leap(int a){
if(a%100 == 0) return !(a%400);
else return !(a%4);
}
int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
clock_t start, end;
start = clock();
#endif
int t;
cin >> t;
string s;
while(t--){
int y,m,d,modify=0,after=1;
cin >> y >> m >> d;
m=-m;
d=-d;
if(m == 2 && d == 29){
cout << -1 << endl;
continue;
}else if(m<=2 && d<=28) after = 0;
for(int i = y;i<=y+17;i++){
if(is_leap(i)){
if(!after){
modify++;
}
}else{
if(is_leap(i+1)){
if(after){
modify++;
}
}
}
}
cout << modify + 365*18 << endl;
}
#ifdef LOCAL
end = clock();
cout << "*************************" << endl;
cout<< "Computing time: "<<(double)(end - start)*1000 / CLOCKS_PER_SEC<<"ms"<<endl;
#endif
return 0;
}
我这里采用了增量的形式,在18*365
天的基础上加上多出来的那几天。为啥只取到y+17
呢?因为我们只用考虑这一年变到下一年的情形。第18年不会再变到下一年,所以只计算到y+17
为止。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。