LOJ#3379. 「CSP-S 2020」儒略日
这题考场思路大体是对的,结果挂成了 40。。。
把 \(r_i\) 分为三个区间:\([1,1721424],[1721425,2299161],[2299162,+\infty)\),分别代表公元前、公元元年至 1582 年 10 月 4 日、1582 年 10 月 15 日以后。
对于每一个区间,大题思路就是二分年份,算出每一个 \(r_i\) 所对应的年 \(year\),然后暴力枚举它的 \(month\) 和 \(day\)。前两个区间都比较好处理,对于第三个区间,可以看作闰年判定法则不一样的第二个区间加上十天。把公元元年到儒略日 \(r_i\) 多过的那些 2 月 29 日减掉(100,200,300,500,600,700,900,1000,1100,1300,1400,1500 年的 2 月 29 日,共 \(12\) 天),然后按照第二个区间的写法去写就行了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
void read(ll &x)
{
x=0ll;ll f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1ll;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
x*=f;
}
const int Month[14][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},{0,0}};
// JAN, FEB, MAR, APRIL, MAY, JUNE, JULY, AUG , SEP, OCT, NOV, DEC
void calc(ll n)
{
n++;
if(n<=1721424)
{
ll year=-4714;
ll l=-4713,r=-1;
while(l<=r)
{
ll mid=(l+r)/2ll;
ll tmp=4714-abs(mid);
if((tmp+3ll)/4ll + tmp*365ll<n)
{
year=mid;
l=mid+1;
}
else r=mid-1;
}
ll Tmp=4714-abs(year);
n-=(Tmp+3ll)/4ll + Tmp*365ll;
year++;
if(abs(year)%4==1)
{
int sum=0,month;
for(month=1;month<=12;month++)
{
sum+=Month[month][1];
if(sum>=n)
{
sum-=Month[month][1];
break;
}
}
printf("%lld %d %lld BC",n-sum,month,abs(year));
}
else
{
int sum=0,month;
for(month=1;month<=12;month++)
{
sum+=Month[month][0];
if(sum>=n)
{
sum-=Month[month][0];
break;
}
}
printf("%lld %d %lld BC",n-sum,month,abs(year));
}
}
else if(n<=1721424+577460+277)
{
n-=1721424;
ll l=1ll,r=1583;
ll year=0;
while(l<=r)
{
ll mid=(l+r)/2;
if(mid*365ll+mid/4ll<n)
{
l=mid+1;
year=mid;
}
else r=mid-1;
}
n-=year*365ll+year/4ll;
year++;
if(year%4==0)
{
int sum=0,month;
for(month=1;month<=12;month++)
{
sum+=Month[month][1];
if(sum>=n)
{
sum-=Month[month][1];
break;
}
}
printf("%lld %d %lld",n-sum,month,abs(year));
}
else
{
int sum=0,month;
for(month=1;month<=12;month++)
{
sum+=Month[month][0];
if(sum>=n)
{
sum-=Month[month][0];
break;
}
}
printf("%lld %d %lld",n-sum,month,abs(year));
}
}
else
{
n+=10;
n-=12;
n-=1721424;
ll l=1,r=(ll)1e9;
ll year=0;
while(l<=r)
{
ll mid=(l+r)/2;
if(mid*365ll+mid/4ll - mid/100ll + mid/400ll<n)
{
l=mid+1;
year=mid;
}
else r=mid-1;
}
n-=year*365ll + year/4ll - year/100ll + year/400ll;
year++;
if(year%400==0 || (year%4==0 && year%100!=0))
{
int sum=0,month;
for(month=1;month<=12;month++)
{
sum+=Month[month][1];
if(sum>=n)
{
sum-=Month[month][1];
break;
}
}
printf("%lld %d %lld",n-sum,month,abs(year));
}
else
{
int sum=0,month;
for(month=1;month<=12;month++)
{
sum+=Month[month][0];
if(sum>=n)
{
sum-=Month[month][0];
break;
}
}
printf("%lld %d %lld",n-sum,month,abs(year));
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll x;
scanf("%lld",&x);
calc(x);
putchar('\n');
}
}