【题解】[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;
}
posted @ 2020-11-09 10:55  破壁人五号  阅读(514)  评论(0编辑  收藏  举报