[CSP-S2020] 儒略日 题解

[CSP-S2020] 儒略日

今儿终于做掉困扰多年的题目了,其实想好细节也不难。

容易发现儒略历和格里高利历的润年判断方式不一样,并且中间有消失的十天,计算起来相当不方便。所以我们可以首先计算出 \(-4713.1.1\)\(1582.10.4\) 会经过多少天,可以通过一天一天暴力跳的方法计算出需要 \(2299160\),那么对于小于等于该数字的情况,直接按照儒略历的计算方式从 \(-4713.1.1\) 计算即可,否则先将天数减去 \(2299161\) 然后按照格里高利历从 \(1582.10.15\) 开始计算。

对于儒略历,可以发现,4年一闰,所以先除掉4年的天数,然后一月一月的跳,最后一天一天地跳。

对于格里高利历,400年总共有97闰,所以先400年跳,然后一年一年跳,再一月一月跳,最后一天一天跳。

对于代码实现,可以使用查表的方式简化计算。

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
LL read() {
    LL sum=0,flag=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') flag=-1; c=getchar();}
    while(c>='0'&&c<='9') {sum=sum*10+c-'0'; c=getchar();}
    return sum*flag;
}

#define int LL
int T;
int year[2]={365,366};
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}};

inline int chkru(int x) {
    if(x<0) x++;
    if(x%4==0) return 1;
    else return 0;
}

inline int chkge(int x) {
    if((x%4==0&&x%100!=0)||x%400==0) return 1;
    else return 0;
}

inline void calc_ru(int n) {
    int a=-4713,b=1,c=1;
    a=a+4*int(n/1461); n%=1461;
    if(a>=0) a++;
    while(n>=month[b][chkru(a)]) {
        n-=month[b][chkru(a)];
        b++;
        if(b==13) {
            b=1;
            if(a==-1) a=1;
            else a++;
        }
    }
    while(n--) {
        c++;
        if(c==month[b][chkru(a)]+1) {
            c=1; b++;
            if(b==13) {
                b=1;
                if(a==-1) a=1;
                else a++;
            }
        }
    }
    if(a<0) cout<<c<<" "<<b<<" "<<-a<<" BC"<<endl;
    else cout<<c<<" "<<b<<" "<<a<<endl;
}

inline void calc_ge(int n) {
    int a=1582,b=10,c=15;
    a=a+400*int(n/146097); n%=146097;
    while(n>=year[chkge(a+1)]) {
        n-=year[chkge(a+1)];
        a++;
    }
    while(n>=month[b][chkge(a)]) {
        n-=month[b][chkge(a)];
        b++; if(b==13) {b=1; a++;}
    }
    while(n--) {
        c++;
        if(c==month[b][chkge(a)]+1) {
            c=1; b++;
            if(b==13) {b=1; a++;}
        }
    }
    cout<<c<<" "<<b<<" "<<a<<endl;
}

signed main() {
    cin>>T;
    while(T--) {
        int n; cin>>n;
        if(n<=2299160) calc_ru(n);
        else calc_ge(n-2299161);
    }
}
posted @ 2023-10-30 21:45  2017BeiJiang  阅读(30)  评论(0编辑  收藏  举报