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

简介: 蓝桥杯练习题七 - 第几天(c++)

题目如下


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


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


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

#include <cstdio>
#include <algorithm>
using namespace std;
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}};
bool isleap(int year)
{
    return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
int main()
{
    int y1, m1, d1;
    int y2, m2, d2;
    int time1, time2;
    scanf("%d%d", &time1, &time2);
    if (time1 > time2)
        swap(time1, time2);
    y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
    y1 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;
    int ans = 1;
    while (y1 < y2 || m1 < m2 || d1 < d2)
    {
        d1++;
        _________________;
        ans++;
    }
    printf("%d\n", ans);
    return 0;
}

题目分析


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


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


代码如下:

#include<iostream>
using namespace std;
int Num(int y, int m, int d)
{
    int flag = 0;
    if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
    {
        flag = 1;
    }
    vector<int>arr{ 31,28,31,30,31,30,31,31,30,31,30,31 };
    if (m == 1)
        return d;
    else if (m == 2)
        return arr[m - 1] + d;
    else
        return accumulate(arr.begin(), arr.begin() + m - 1, 0) + flag + d;
}
int main()
{
    cout << Num(2000, 7, 7);//189
}


1.判断平年和闰年

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

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


2. 计算天数


    vector<int>arr{ 31,28,31,30,31,30,31,31,30,31,30,31 };
    if (m == 1)
        return d;
    else if (m == 2)
        return arr[m - 1] + d;
    else
        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.png

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


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


代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
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}};
bool isleap(int year)
{
    return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
int main()
{
    int y1, m1, d1;
    int y2, m2, d2;
    int time1, time2;
    scanf("%d%d", &time1, &time2);
    if (time1 > time2)
        swap(time1, time2);
    y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
    y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;
    int ans = 1;
    while (y1 < y2 || m1 < m2 || d1 < d2)
    {
        d1++;
        if (d1 == month[m1][isleap(y1)] + 1)
        {
            d1 = 1;
            m1++;
        }
        if (m1 == 13)
        {
            m1 = 1;
            y1++;
        }
        ans++;
    }
    printf("%d\n", ans);
    return 0;
}

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


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}};
bool isleap(int year)
{
    return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}

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


2.日期处理

    int y1, m1, d1;
    int y2, m2, d2;
    int time1, time2;
    scanf("%d%d", &time1, &time2);
    if (time1 > time2)
        swap(time1, time2);
    y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
    y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;

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


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


3.运算部分

    int ans = 1;
    while (y1 < y2 || m1 < m2 || d1 < d2)
    {
        d1++;
        if (d1 == month[m1][isleap(y1)] + 1)
        {
            d1 = 1;
            m1++;
        }
        if (m1 == 13)
        {
            m1 = 1;
            y1++;
        }
        ans++;
    }

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。


总结:


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

目录
相关文章
|
2月前
|
算法 测试技术 C++
【动态规划算法】蓝桥杯填充问题(C/C++)
【动态规划算法】蓝桥杯填充问题(C/C++)
|
2月前
|
人工智能 算法 BI
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
|
2月前
|
人工智能 C++
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
|
7月前
|
网络安全
蓝桥杯-网络安全-练习题-crypto-rsa
蓝桥杯-网络安全-练习题-crypto-rsa
蓝桥杯-网络安全-练习题-crypto-rsa
|
2月前
|
机器学习/深度学习 算法 关系型数据库
第十五届蓝桥杯C++B组省赛
第十五届蓝桥杯C++B组省赛
111 14
|
2月前
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
51 5
|
7月前
|
算法 测试技术 C++
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
|
7月前
|
算法 C++ 数据格式
小唐开始刷蓝桥(七)2014年第五届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(七)2014年第五届C/C++ B组蓝桥杯省赛真题
|
7月前
|
算法 C++
小唐开始刷蓝桥(五)2016年第七届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(五)2016年第七届C/C++ B组蓝桥杯省赛真题
|
7月前
|
算法 C++
小唐开始刷蓝桥(六)2015年第六届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(六)2015年第六届C/C++ B组蓝桥杯省赛真题