本来以为和上次那个简单题一样的,没啥难度,就是循环就完事了,结果超时了
超时代码:
#include <iostream>
using namespace std;
//平年各个月份都多少天?
int mouths [13] = {
0,31,28,31,30,31,30,31,31,30,31,30,31
};
//判断此年是闰年还是平年 是润年就返回一,不是则返回0
int judge_year(int year){
if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
return 1;
}
return 0;
}
//返回某年某月一共多少天?
int dayOfmouth(int year ,int mouth){
if(mouth == 2 && judge_year(year) == 1)
return mouths[mouth] + 1;
else return mouths[mouth];
}
int main(){
int year , day , mouth , lenOfday;
int n;
cin>>n;
while(n--){
cin>>year>>mouth>>day>>lenOfday;
int mouth1 = mouth , day1 = day;
while( lenOfday-- ){
day1 ++;
// cout<<day1<<"-"<<mouth<<endl;
if(day1 > dayOfmouth(year,mouth1)){
day1 = 1;
mouth1++;
if(mouth1 > 12){
mouth1 = 1;
year++;
}
}
}
printf("%04d-%02d-%02d\n",year,mouth1,day1);
}
return 0;
}
超时样例:
1000
2091 6 29 634830
2115 4 21 22027
1946 8 9 854350
2056 6 3 715810
2782 9 4 796922
1699 12 15 184655
1247 6 11 638360
2408 8 21 879227
1147 8 25 773890
1057 8 7 348039
2371 10 29 935478
1912 2 27 999934
2427 9 14 92640
1983 3 7 348930
1499 8 5 596979
2796 5 26 515616
1792 8 30 740722
2747 11 11 330057
1773 4 30 875893
2372 7 22 371697
1237 8 18 586546
1169 11 20 513740
1998 4 23 346024
2745 3 31 84795
1305 11 9 95146
1284 2 14 597099
2341 9 5 395133
2033 8 10 551638
1762 12 25 347636
2917 3 19 74113
1398 5 28 21974
2893 11 1 272578
2217 1 1 243153
1028 5 25 518800
2562 4 23 547192
1630 9 2 579462
2979 7 23 923800
2694 11 6 646394
2350 8 7 235079
2382 7 16 704178
1630 4 8 192872
1105 2 22 39505
1984 1 20 66417
1723 9 26 247094
1245 12 23 987206
1818 12 20 732915
2037 10 8 731946
1449 11 3 754965
1859 12 31 523183
2975 11 5 619971
2013 11 25 928027
2995 2 22 298059
1720 10 10 620280
1448 7 15 204194
1020 5 15 225758
2512 2 9 632627
2395 11 19 252286
2489 6 29 852785
1496 10 13 601134
1779 11 5 737765
1567 7 7 836958
1711 1 1 277110
2968 5 13 291651
2567 3 1 881136
2201 1 21 857540
2550 3 27 754188
1671 3 17 235695
1803 7 2 489657
1342 1 13 280616
2795 6 14 297831
2111 7 31 142825
1564 6 14 212124
2201 4 17 961987
2607 6 6 124318
1037 12 11 147447
2941 3 7 541281
1262 9 16 540441
1499 3 14 490286
1797 11 10 71749
1790 4 22 308694
2083 4 29 575426
2681 6 23 604999
1022 12 27 720711
2029 9 27 550751
2534 4 17 273081
2625 6 11 689417
2242 11 26 964762
1021 1 13 433612
2822 6 17 356140
1986 4 13 329179
2159 12 24 252720
2161 10 28 492323
2064 4 4 3405
1823 3 23 441953
2691 12 14 727889
1796 3 7 672592
1885 6 14 976246
2166 11 17 283102
1476 1 12 234669
2190 11 2 57086
1503 2 26 543206
1010 2 28 704316
2228 3 19 847779
1150 7 8 275086
1385 11 25 176706
2363 9 11 401377
2015 6 29 590936
2885 11 14 922651
1710 9 2 543485
2452 11 6 101538
1912 10 10 924722
1508 2 28 903629
1993 11 23 905684
1376 2 20 557365
1153 8 9 186995
2449 5 31 813330
2416 4 7 842671
2578 8 11 85095...
这段代码会被执行多少次?
拿出计算器一算 6后面8个0,这不完全超过了y总说的10的八次方
怪不得超时,看来要优化一下了。
看了y总的视屏,其实就是先枚举年数,再枚举天数。于是我写了下面这段代码
int get_days_year(int year){
return judge_year(year)+365;
}
while(lenOfday > get_days_year(year)){
lenOfday = lenOfday - get_days_year(year);
year ++;
}
结果答案错误,其实是我想错了,往上加一年不是看今年有多少天,而是看下一年的今天到今年的今天中间差了多少天。
我们需要通过不同的月份来判断,如果今年我们输入的样例是在1月1号到2月28日之间的,那么我们需要跳过的是当年是否为闰年,但是如果是3月1日到12月31日之间的,我们需要跳过的是下一年的2月,所以我们要判断下一年是否为闰年。
于是上面的代码我们就改为:
int get_days_year(int year,int mouth){
if(mouth<=2)return judge_year(year)+365;
return judge_year(year + 1)+365;
}
while(lenOfday > get_days_year(year,mouth1)){
lenOfday = lenOfday - get_days_year(year,mouth1);
year ++;
}
有人就会问了,万一我这次输入的样例正好是2月29呢?我今年虽然是闰年但是我已经不用跳过这一天了啊,所以应该算平年,没错,确实是这样,但是如果把这个逻辑加入这个函数里就不这个函数的功能就不清楚了,或者说逻辑比较乱,所以我们为了图方便就在枚举之前先做一次特判。
if(mouth1 == 2 && day1 == 29) lenOfday--, mouth1++ , day1 = 1;
于是我们就可以写出代码。
#include <iostream>
using namespace std;
//平年各个月份都多少天?
int mouths [13] = {
0,31,28,31,30,31,30,31,31,30,31,30,31
};
//判断此年是闰年还是平年 是润年就返回一,不是则返回0
int judge_year(int year){
if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
return 1;
}
return 0;
}
//返回某年某月一共多少天?
int dayOfmouth(int year ,int mouth){
if(mouth == 2 && judge_year(year) == 1)
return mouths[mouth] + 1;
else return mouths[mouth];
}
//除去特判情况算出今年某个日子到下一年同一天中间隔了多少天
int get_days_year(int year,int mouth){
if(mouth<=2)return judge_year(year)+365;
return judge_year(year + 1)+365;
}
int main(){
int year , day , mouth , lenOfday;
int n;
cin>>n;
while(n--){
cin>>year>>mouth>>day>>lenOfday;
int mouth1 = mouth , day1 = day;
//特判
if(mouth1 == 2 && day1 == 29) lenOfday--, mouth1++ , day1 = 1;
//遍历年份,优化部分
while(lenOfday > get_days_year(year,mouth1)){
lenOfday = lenOfday - get_days_year(year,mouth1);
year ++;
}
while( lenOfday-- ){
day1 ++;
if(day1 > dayOfmouth(year,mouth1)){
day1 = 1;
mouth1++;
if(mouth1 > 12){
mouth1 = 1;
year++;
}
}
}
printf("%04d-%02d-%02d\n",year,mouth1,day1);
}
return 0;
}
对了,最后讲一下为啥这个代码就可以不超时了:因为题目给出lenOfday是不会超过1的六次方的。我们假设个最坏的情况:每个测试样例都是1的六次方,但是我们在枚举天数的前面先枚举了年份,也只有2739次,然后后面枚举天数也最多365天,加起来3200不到,然后再最坏的打算,有1000个样例点,那么就是32后面五个零那么也是远远小于下边界10的7次方的。所以不超时。