• 蓝桥杯练习题七 - 第几天(c++)


    题目如下

     

    y年m月d日是哪一年的第几天。

    比如y年的1月1日是那一年的第一天,那么2000年7月7日是那一年的第几天。

    以下程序实现了该功能,请你补全空白处代码:

    1. #include <cstdio>
    2. #include <algorithm>
    3. using namespace std;
    4. int month[13][2] = {{0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}};
    5. bool isleap(int year)
    6. {
    7. return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
    8. }
    9. int main()
    10. {
    11. int y1, m1, d1;
    12. int y2, m2, d2;
    13. int time1, time2;
    14. scanf("%d%d", &time1, &time2);
    15. if (time1 > time2)
    16. swap(time1, time2);
    17. y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
    18. y1 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;
    19. int ans = 1;
    20. while (y1 < y2 || m1 < m2 || d1 < d2)
    21. {
    22. d1++;
    23. _________________;
    24. ans++;
    25. }
    26. printf("%d\n", ans);
    27. return 0;
    28. }

    题目分析 

    正常博主都是先给出最终答案,然后才开始分析具体实现,今天咱们先分析下这个题目,因为可能会误导一部分人。题目中给出的是计算某个日期是当年的第几天,而代码中却存在两个日期,解释下原因,题目中计算的是两个日期之间相差多少天,这多少和题目本意还是差了点意思,为了让大家两种都能学习到,这里博主把两种方式的代码都来解读分析下。

    第一种:当前日期是当年的第几天 

    代码如下:

    1. #include
    2. using namespace std;
    3. int Num(int y, int m, int d)
    4. {
    5. int flag = 0;
    6. if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
    7. {
    8. flag = 1;
    9. }
    10. vector<int>arr{ 31,28,31,30,31,30,31,31,30,31,30,31 };
    11. if (m == 1)
    12. return d;
    13. else if (m == 2)
    14. return arr[m - 1] + d;
    15. else
    16. return accumulate(arr.begin(), arr.begin() + m - 1, 0) + flag + d;
    17. }
    18. int main()
    19. {
    20. cout << Num(2000, 7, 7);//189
    21. }

    1.判断平年和闰年

    1. int flag = 0;
    2. if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
    3. {
    4. flag = 1;
    5. }

    这个比较简单,应该没有看不懂的吧?默认跳过了。

    2. 计算天数

    1. vector<int>arr{ 31,28,31,30,31,30,31,31,30,31,30,31 };
    2. if (m == 1)
    3. return d;
    4. else if (m == 2)
    5. return arr[m - 1] + d;
    6. else
    7. return accumulate(arr.begin(), arr.begin() + m - 1, 0) + flag + d;

    罗列出平年每一月的天数后:

    如果是1月,日期就是第几天;

    如果是2月,arr[m-1]+d就是天数;

    其他月份,当前月前面的所有天数相加,再加上当前月的日,如果是闰年,需要额外+1,flag已经做出了判断。

    说下accumulate

    int sum = accumulate(array.begin() , array.end() , 0);  

    accumulate 有三个参数:头两个参数是要累加的元素范围,第三个参数是累加的初始值。

    accumulate 函数将它的一个内部变量设置为一个指定的初始值,然后在此初值上累加输入范围内所有元素的值。accumulate 算法返回累加的结果,其返回类型就是其第三个实参的类型。

    accumulate还可用于拼接字符串:

    string str = accumulate(array.begin() , array.end() , string(""));  

     到这里,第一种单纯算天数的解法就结束了,是不是很简单呢?接下来,我们开始第二种,计算距离某个日期的天数。

     第二种:当前日期距某个日期的天数

    代码如下:

    1. #include
    2. #include
    3. using namespace std;
    4. int month[13][2] = {{0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}};
    5. bool isleap(int year)
    6. {
    7. return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
    8. }
    9. int main()
    10. {
    11. int y1, m1, d1;
    12. int y2, m2, d2;
    13. int time1, time2;
    14. scanf("%d%d", &time1, &time2);
    15. if (time1 > time2)
    16. swap(time1, time2);
    17. y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
    18. y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;
    19. int ans = 1;
    20. while (y1 < y2 || m1 < m2 || d1 < d2)
    21. {
    22. d1++;
    23. if (d1 == month[m1][isleap(y1)] + 1)
    24. {
    25. d1 = 1;
    26. m1++;
    27. }
    28. if (m1 == 13)
    29. {
    30. m1 = 1;
    31. y1++;
    32. }
    33. ans++;
    34. }
    35. printf("%d\n", ans);
    36. return 0;
    37. }

    这是题目中给出的代码补全后的样子,个人认为还有优化提升空间,简化步骤,大家自行思考。

    1. 判断平闰年

    1. int month[13][2] = {{0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31}};
    2. bool isleap(int year)
    3. {
    4. return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
    5. }

    判断平闰年不是个难事,不多加说明,说说这个多维数组吧,很有意思啊,其实也就是按照月份,每个月在平闰年的天数,第0月用0补齐,说实话,觉得有些鸡肋了。

    2.日期处理

    1. int y1, m1, d1;
    2. int y2, m2, d2;
    3. int time1, time2;
    4. scanf("%d%d", &time1, &time2);
    5. if (time1 > time2)
    6. swap(time1, time2);
    7. y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
    8. y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;

    这里输入两个日期,time1大于time2,则交换两个日期,而且题目中y2也写成了y1,此处已纠正,并已经找官方修改。

    由于输入的日期是不带分隔符的数字,比如:2022.08.28,输入是20220828,所以为了获取到年月日,需要按照上面的方式整除或者整除取余来获取年月日。

    3.运算部分

    1. int ans = 1;
    2. while (y1 < y2 || m1 < m2 || d1 < d2)
    3. {
    4. d1++;
    5. if (d1 == month[m1][isleap(y1)] + 1)
    6. {
    7. d1 = 1;
    8. m1++;
    9. }
    10. if (m1 == 13)
    11. {
    12. m1 = 1;
    13. y1++;
    14. }
    15. ans++;
    16. }

    ans是天数,默认为1。

    y1 < y2 || m1 < m2 || d1 < d2这是前提,如果想等,就是计算到头了。

    判断1:

    d1++,d1 == month[m1][isleap(y1)] + 1,判断平润年,从month的二位数组中取出对应年份对应月份的天数,+1是判断d1超出了这个月的最大天数,这时候就到下个月了,m1要+1,d1要重置为下个月的1号。

    判断2:

    m1=13,则带白哦要进入下一年了,进入下一年,年份y1+1,月份m1重置为1.


    然后每次运算,ans++,直到y1=y2,m1=m2,d1=d2,则退出while循环,输出最终天数ans。

    总结:

    这道题难度不高,主要还是一个细心,考研对平闰年的判断和逻辑的思考方式,题目给的不是很明确,没搞懂的话很容易进入思维误区。有问题,欢迎评论区留言讨论。

  • 相关阅读:
    mysql回表查询和索引覆盖
    【Python大数据笔记_day06_Hive】
    pugixml XML格式处理库的介绍和使用(面向业务编程-格式处理)
    CentOS 7 安装 Tomcat
    Apache DolphinScheduler 入门(一篇就够了)
    虚假新闻检测概述
    Ubuntu系统如何配置apt远程源
    android获取webView加载H5链接,截取url参数
    将windows命令行的结果保存到文件 (cmd命令的重定向输出)
    Python 算法:学习二分法
  • 原文地址:https://blog.csdn.net/CodingFire/article/details/126567471