P8831 [传智杯 #3 练习赛] 儒略历 题解

· · 题解

调了半天终于对了(

Step 1: 读入

如题我们已知输入的格式是 日 月 年 ,而是用字符串表示,所以我们需要把哪一月份给求出来。

根据题目给的缩写,我们就可以打表来计算月份。

string month[13]={"","JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};

由于我们读入的是个字符串,所以我们紧接着还要把年和日求出来,先求日,再求年。

把字符串转化成数字这应该人人皆知如何处理,这里不做细讲。我们先把前面的数字给,直到出现了字符,我们之后出现的数字才给

for(int i=0;i<st.size();i++){
    if(st[i]>='0'&&st[i]<='9'){
        if(!ok)d*=10,d+=int(st[i]-48ll);//在出现字符之前计算日。
        else y*=10,y+=int(st[i]-48ll);//在出现字符后计算年。
    }
    else mon+=st[i],ok=1;//ok 代表是否出现了字符,mon最终是月份的字符串。
}

别问我为什么是减去 48ll ,只是防止 ctjer。

把月份化成数字也就很方便了。

for(int i=1;i<=12;i++)
    if(mon==month[i]){//正好匹配到一样的月份,i 的值即为月份。
        m=i;
        break;
    }

Step 2: 计算天数

题目由此可以化简为:我们已知现在是 y 年 m 月 d 日,求离 1 年 1 月 1 日多少天。

显然的,y 年不一定过完了,m 月也不一定过完了,所以我们不能直接加到它们的值,而是要到它们的值 -1。

由题我们又可以把月份分成3种情况:

  1. \lt 1582 ,闰年只需判断是否能被 4 整除。
  2. = 1582,不是闰年,10 月少了 10 天
  3. \gt 1582,闰年包括普通和世纪闰年。

普通闰年:能被 4 整除不能被 100 整除。

世纪闰年:能被 400 整除。

拓展芝士:闰秒将在2035年取消。

根据上述条件,我们也就可以得出代码啦。

代码如下:

#include<bits/stdc++.h>
using namespace std;
string month[13]={"","JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//每个月的天数
signed main()
{
    int d=0,m=0,y=0;
    string st,mon="";
    bool ok=0;
    cin>>st;
    for(int i=0;i<st.size();i++){
        if(st[i]>='0'&&st[i]<='9'){
            if(!ok)d*=10,d+=int(st[i]-48ll);//在出现字符之前计算日。
            else y*=10,y+=int(st[i]-48ll);//在出现字符之前计算年。
        }
        else mon+=st[i],ok=1;//ok 代表是否出现了字符,mon最终是月份的字符串。
    }
    for(int i=1;i<=12;i++)
        if(mon==month[i]){//正好匹配到一样的月份,i 的值即为月份。
            m=i;
            break;
        }
    //cout<<y<<' '<<m<<' '<<d<<'\n';
    if(y<1582)a[2]=(y%4==0?29:28);;//第一种情况。
    else if(y==1582)a[2]=28;;//第二种情况。
    else a[2]=(y%4==0&&y%100!=0||y%400==0?29:28);;//第三种情况。
    if(y==1582&&m>=10&&d>=15)d-=10;//如果正好在1582年的10月15号及以后,减去 10。
    while(m--)d+=a[m];//完整走完的月的总天数。
    while(y--&&y){//完整走完的年的总天数
        if(y<1582)d+=(y%4==0?366:365);//第一种情况。
        else if(y==1582)d+=355;//第二种情况。
        else d+=(y%4==0&&y%100!=0||y%400==0?366:365);//第三种情况。
    }
    cout<<d-1;//因为求的是与 1 年 1 月 1 日之间的天数,d 为天数,所以输出 d-1 。
}

代码可能有点漏洞,如有发现请在评论区指出或私聊我,会及时改正。

毕竟我不想被撤下题解。