【题解】[CSP-S 2020] 儒略日【大模拟】
(题意略)
题解
巨大模拟即可。二分会好些很多。我的写法是:
- 1582 年 10 月 15 日及之后的日子加上 10,毕竟消失的 10 天很毒瘤;
- 关于公元 1 年 1 月 1 日与 1583 年分段处理;
- 实行格里高利历之前先找到这是在哪个四年,然后找到这是在哪一年,然后是哪一月,哪一日;
- 实行格里高利历之后依次找到这是在哪个四百年、哪个百年、哪个四年、哪个年、哪个月、哪一天。
考场上处理错了公元前的闰年的最后一天和 1582 年 10 月 15 日。
代码;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll getint(){
ll ans=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
ans=ans*10+c-'0';
c=getchar();
}
return ans*f;
}
int mo[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
ll d0=0; // the Julian day of 1/1/1
ll d1=0; // the Julian day of 1582/10/15
ll d2=0; // the Julian day of 1583/1/1 if 1582/10/5~14 exists
ll d3=0; // the Julian day of 1583/1/1
// if 1582/10/5~14 exists and people used Gregorian from 1/1/1
int m_(int i,int y){
if(y<0)++y;
if(i!=2)return mo[i];
if(y<=1582)return mo[i]+(y%4==0);
else return mo[i]+(y%4==0&&(y%100!=0||y%400==0));
}
int main(){
for(int i=4712;i>=0;--i)d0+=365+(i%4==0);
d1=d0;
d3=d0;
for(int i=1;i<=1581;i++)d1+=365+(i%4==0);
for(int i=1;i<=1582;i++)d3+=365+(i%4==0&&(i%100!=0||i%400==0));
// now d1 is the Julian day of 1582/1/1
d2=d1+365;
for(int i=1;i<=9;i++)d1+=mo[i];
d1+=4;
/****************** Wrong Code ****************
d1+=5;
* ********************************************/
int n=getint();
while(n--){
ll x=getint();
if(x<d0){
int y=4713-x/(365*4+1)*4;x%=(365*4+1);
if(x>=366){y--,x-=366; // 4713 BC passed
if(x>=365)y--,x-=365; // 4714 BC passed
if(x>=365)y--,x-=365; // 4715 BC passed
//if(x>=365)assert(0); // 4716 BC passed (This shouldn't happen)
}
/****************** Wrong Code ****************
if(x>=366)y--,x-=366; // 4713 BC passed
if(x>=365)y--,x-=365; // 4714 BC passed
if(x>=365)y--,x-=365; // 4715 BC passed
//if(x>=365)assert(0); // 4716 BC passed (This shouldn't happen)
* ********************************************/
int m=1;
while(x-m_(m,-y)>=0)x-=m_(m,-y),m++;
int d=x+1;
printf("%d %d %d BC\n",d,m,y);
continue;
}
if(x>=d1)x+=10; // Don't care about the lost 10 days elsewhere
if(x>=d0&&x<d2){
x-=d0;
int y=x/(365*4+1)*4+1;x%=(365*4+1);
if(x>=365)y++,x-=365; // 1 passed
if(x>=365)y++,x-=365; // 2 passed
if(x>=365)y++,x-=365; // 3 passed
//if(x>=366)assert(0); // 4 passed (This shouldn't happen)
int m=1;
while(x-m_(m,y)>=0)x-=m_(m,y),m++;
int d=x+1;
printf("%d %d %d\n",d,m,y);
continue;
}
if(x>=d2){
x-=d0;
x+=d3-d2;
int y=x/(365*400+24*4+1)*400+1;x%=(365*400+24*4+1);
if(x>=365*100+24)y+=100,x-=365*100+24;
if(x>=365*100+24)y+=100,x-=365*100+24;
if(x>=365*100+24)y+=100,x-=365*100+24;
//if(x>=365*100+25)assert(0);
y+=x/(365*4+1)*4,x%=(365*4+1);
if(x>=365)y++,x-=365; // 1 passed
if(x>=365)y++,x-=365; // 2 passed
if(x>=365)y++,x-=365; // 3 passed
if(x>=366)assert(0); // 4 passed (This shouldn't happen)
int m=1;
while(x-m_(m,y)>=0)x-=m_(m,y),m++;
int d=x+1;
printf("%d %d %d\n",d,m,y);
continue;
}
}
// cerr<<"\n\nFinished after "<<clock()/1000.0<<" second(s)."<<endl;
return 0;
}