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');
	}
}
posted @ 2020-12-04 15:54  zzt1208  阅读(189)  评论(0编辑  收藏  举报