https://vjudge.net/problem/HD...ios
一句话题意:给定出生日期(格式为
1988-03-07
),求到18岁生日为止经历了多少天;没有18岁生日输出-1。算法
这个题目太普通了,相似的问题可能满大街都是。这不是一个算法竞赛等级的题目,可是仍是有的好说。我要记录的是我作这题的思考方式。函数
解:spa
首先考虑闰年。通常来讲,公元闰年的肯定方法以下:年份若为400的正整倍数
时,闰;不然,年份是4的正整倍数
且不是100的正整倍数
时,闰;都不符合,平。这点体如今函数is_leap
里。.net
我发现,若今年是闰年,日期在2月29日以前或以后的两种情形到“明年今日”的天数是不一样的。如2008-03-01
到2009-03-01
经历366
天,2008-02-28
到2009-02-28
经历365
天。code
对称地,若今年是平年,明年是闰年也有相似的规律可说。ci
这就是我要记录的“局部分离思想”。这个问题一开始看很复杂,可是咱们发现,这一年到下一年,无非只有3种大情形。日期在2月29日以前简记为“前”;日期在这以后(含)简记为“后”。列表以下。get
平=>平
前365天;后365天string
平=>闰
前365天;后366天it
闰=>平
前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
为止。