【CSP2020】 T1儒略日
NOIPCSP2020终于结束辣,可是这跟我一个大一学生有什么关系呢?,作为曾经的OI狗,也作为准备冲击ACM校队的一名蒟蒻,我决定做一做今年的题。
题目链接
https://www.luogu.com.cn/problem/P7075?contestId=37022
本题是一道显然的大模拟,思路很简单,但是需要考虑的细节实在是太多力QwQ,窝写了4个多小时才A掉此题(想必如果真在赛场就要喜提省四了罢),最终发现少写了一个return。。。
简单讲一下一些优化技巧吧,首先,可以写一个函数计算每年的第几天是几月几日,减少大量重复操作。而且,接下来只要考虑年份和天数,去除了干扰因素。同时,利用题目信息,将问题分段。对于格里高利历,有400和100对闰年的影响,可以将1582年到1599年单独分一组,这样,从1600年1月1日开始,就可以400年一个周期,变得有规律了。
代码
#include<cstdio>
#include<cstdlib>
#define ll long long
using namespace std;
int d[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
};
struct date{
bool BC;
int month,day;
ll year;
};
date f(int x,int flag,int isBC){
int i;
date ans;
ans.BC=isBC;
for(i=1;i<=12;i++){
if(x<=d[flag][i]){
ans.month=i;ans.day=x;
return ans;
}
x-=d[flag][i];
}
}
date julian(ll x){
date ans;
int tmp=4713*365+4712/4+1;
if(x<=tmp){//BC
ll t=(x-1)/(4*365+1);
ll r=x-t*(4*365+1);
ll y=4713-t*4;
if(r>366){
y--;r-=366;
}
else{
ans=f(r,1,1);
ans.year=y;
return ans;
}
if(r>365){
y--;r-=365;
}
else{
ans=f(r,0,1);
ans.year=y;
return ans;
}
if(r>365){
y--;r-=365;
}
else{
ans=f(r,0,1);
ans.year=y;
return ans;
}
ans=f(r,0,1);
ans.year=y;
return ans;
}
else{//AD
x-=tmp;
tmp=1581*365+1582/4+277;
if(x<=tmp){//julian
ll t=(x-1)/(4*365+1);
ll r=x-t*(4*365+1);
ll y=4*t+1;
if(r>365){
y++;r-=365;
}
else{
ans=f(r,0,0);
ans.year=y;
return ans;
}
if(r>365){
y++;r-=365;
}
else{
ans=f(r,0,0);
ans.year=y;
return ans;
}
if(r>365){
y++;r-=365;
}
else{
ans=f(r,0,0);
ans.year=y;
return ans;
}
ans=f(r,1,0);
ans.year=y;
return ans;
}
else{//new
x+=10-tmp;
if(x<=88+(1600-1583)*365+4){//before 1600 1 1
if(x<=88){//this year
ans=f(x+277,0,0);
ans.year=1582;
return ans;
}
else{
x-=88;
for(int i=1583;i<1600;i++){
int kkk;
if(!(i%4)) kkk=1;
else kkk=0;
if(x<=365+kkk){
ans=f(x,kkk,0);
ans.year=i;
return ans;
}
x-=365+kkk;
}
}
}
else{//after 1600 1 1
x-=88+(1600-1583)*365+4;
ll t=(x-1)/(400*365+100-4+1);
ll y=1600+t*400;
x-=t*(400*365+100-4+1);
if(x<=100*365+25){
ll tt=(x-1)/(4*365+1);
ll r=x-tt*(4*365+1);
y+=tt*4;
if(r>366){
y++;r-=366;
}
else{
ans=f(r,1,0);
ans.year=y;
return ans;
}
if(r>365){
y++;r-=365;
}
else{
ans=f(r,0,0);
ans.year=y;
return ans;
}
if(r>365){
y++;r-=365;
}
else{
ans=f(r,0,0);
ans.year=y;
return ans;
}
ans=f(r,0,0);
ans.year=y;
return ans;
}
else{
x-=(100*365+25);
y+=100;
ll tt=(x-1)/(100*365+25-1);
ll r=x-tt*(100*365+25-1);
y+=tt*100;
if(r>31+28) r++;
tt=(r-1)/(4*365+1);
r=r-tt*(4*365+1);
y+=tt*4;
if(r>366){
y++;r-=366;
}
else{
ans=f(r,1,0);
ans.year=y;
return ans;
}
if(r>365){
y++;r-=365;
}
else{
ans=f(r,0,0);
ans.year=y;
return ans;
}
if(r>365){
y++;r-=365;
}
else{
ans=f(r,0,0);
ans.year=y;
return ans;
}
ans=f(r,0,0);
ans.year=y;
return ans;
}
}
}
}
}
int main(){
int T,i,j;
ll x;
date ans;
// freopen("julian3.in","r",stdin);
// freopen("out.txt","w",stdout);
scanf("%d",&T);
for(i=1;i<=T;i++){
scanf("%lld",&x);
ans=julian(x+1);
printf("%d %d %lld",ans.day,ans.month,ans.year);
if(ans.BC) printf(" BC");
printf("\n");
}
return 0;
}