题解:P7075 [CSP-S2020] 儒略日

· · 题解

update:发现了一处错别字

题意

给出一个儒略日日期,需要我们将它转化成格里高利历(公历)日期。\ 推荐一个好用的小工具,可以帮助检验代码问题:儒略日数和日干支计算器,注意表格中的日期如果是公元前的话要减一,建议看中部的蓝字显示的日期。

思路

其实就是暴力模拟,但是需要注意不少要点,也可以说是坑点。

#include <bits/stdc++.h>
#define  int long long
#define  rint register int
#define  ll long long
#define  INF 0x3f3f3f3f
#define  LINF 0x3f3f3f3f3f3f3f3f
#define  bug puts("!!!====!!!=");
using namespace std;
int t,n,day,year,month,aly;
int date[2][13]={0,31,28,31,30,31,30,31,31,30,31,30,31,0,31,29,31,30,31,30,31,31,30,31,30,31};;
bool BC,flag,ru;
bool run(int x){
    if(BC){
        x++;
        if(x%4==0){
            return 1;
        }
        return 0;
    }
    if((x%400==0)||(x%4==0&&x%100!=0)||(x%4==0&&ru)){
        return 1;
    }
    return 0;
}
signed main(){
    BC=1;
    BC=1;
    cin>>t; 
    while(t--){
        cin>>n;
        BC=1;
        ru=1;
        year=-4713;
        month=1;
        day=1;
        while(1){
            if(year==1582){
                ru=0;
            }
            if(!run(year)){
                if(n>=355){
                    n-=355;
                    if(year!=1582){
                        n-=10;
                        if(n<0){
                            n+=365;
                            break;
                        }
                    }
                    year++;
                    if(year==0){
                        year++;
                        BC=0;
                    }
                }
                else{
                    break;
                }
            }
            else{
                if(n>=356){
                    n-=356;
                    if(year!=1582){
                        n-=10;
                        if(n<0){
                            n+=366;
                            break;
                        }
                    }
                    year++;
                    if(year==0){
                        year++;
                        BC=0;
                    }
                }
                else{
                    break;
                }
            }
        }
        flag=run(year);
        while(n--){
            day++;
            if(day==date[flag][month]+1){
                day=1;
                month++;
            }
            if(year==1582&&month==10&&day==5){
                day=15;
            }
        }
        cout<<day<<' '<<month<<' '<<abs(year);
        if(BC){
            cout<<" BC";
        }
        cout<<'\n';
    }
    return 0;
}

那么此刻,很多人既不知道如何优化,又不想重写代码,诶,那么此时,我们会发现一个规律:在 1852 年(既开始使用格里高利历)后,每 400 年为一个周期,那么我们选择 800008000800 来进行循环,只需要在循环时把减去每年的天数变成减去 800008000800 年的天数即可。\ 那么这样我们便得到了一段优化代码:


        while(n-29219400>0){
            n-=29219400;
           year+=80000;
        }
        while(n-2921940>0){
            n-=2921940;
            year+=8000;
        }
        while(n-292194>0){
            n-=292194;
            year+=800;
        }

完整代码

其实一开始我是写火车头的,但是害怕审核直接因为码风不好直接给我毙掉,含泪删代码。

#include <bits/stdc++.h>
#define  int long long
#define  rint register int
#define  ll long long
#define  INF 0x3f3f3f3f
#define  LINF 0x3f3f3f3f3f3f3f3f
#define  bug puts("!!!====!!!=");
using namespace std;
int t,n,day,year,month,aly;
int date[2][13]={0,31,28,31,30,31,30,31,31,30,31,30,31,0,31,29,31,30,31,30,31,31,30,31,30,31};;
bool BC,flag,ru;
bool run(int x){
    if(BC){
        x++;
        if(x%4==0){
            return 1;
        }
        return 0;
    }
    if((x%400==0)||(x%4==0&&x%100!=0)||(x%4==0&&ru)){
        return 1;
    }
    return 0;
}
signed main(){
    BC=1;
    BC=1;
    cin>>t; 
    while(t--){
        cin>>n;
        BC=1;
        ru=1;
        year=-4713;
        month=1;
        day=1;
        if(n>=1721424){
            n-=1721424;
            BC=0;
            year=1;
        }
        while(1){
            if(year==1582){
                ru=0;
            }
            if(!run(year)){
                if(n>=355){
                    n-=355;
                    if(year!=1582){
                        n-=10;
                        if(n<0){
                            n+=365;
                            break;
                        }
                    }
                    year++;
                    if(year==0){
                        year++;
                        BC=0;
                    }
                }
                else{
                    break;
                }
            }
            else{
                if(n>=356){
                    n-=356;
                    if(year!=1582){
                        n-=10;
                        if(n<0){
                            n+=366;
                            break;
                        }
                    }
                    year++;
                    if(year==0){
                        year++;
                        BC=0;
                    }
                }
                else{
                    break;
                }
            }
            if(year==1583){
                break;
            }
        }
        while(n-29219400>0){
            n-=29219400;
           year+=80000;
        }
        while(n-2921940>0){
            n-=2921940;
            year+=8000;
        }
        while(n-292194>0){
            n-=292194;
            year+=800;
        }
        while(n-365>0){
            n-=365;
            if((year%4==0&&year%100!=0)||year%400==0){
                n--;
            }
            year++;
        }
        flag=run(year);
        while(n--){
            day++;
            if(day==date[flag][month]+1){
                day=1;
                month++;
                if(month==13){
                    month=1;
                    year++;
                    flag=run(year);
                }
            }
            if(year==1582&&month==10&&day==5){
                day=15;
            }
        }
        cout<<day<<' '<<month<<' '<<abs(year);
        if(BC){
            cout<<" BC";
        }
        cout<<'\n';
    }
    return 0;
}