「题解」CSP-S 2020 儒略日

谨以此篇题解,纪念我那炸掉的T1。。

基本思路

大模拟,我写了100多行。。

总之就是按照时间依次向后推进

先判断使用哪一历法,当r大于等于2299162时,使用的是格里高利历,反之,使用儒略历。之后分类讨论。

儒略历(r<2299162)

儒略历的话,因为前4713年正好是一个闰年,我就将四年分为了一组,也就是每4年有1461天,算出经过多少年,再算出减去这些年之后还剩的天数(实际上后面都是这个思路)

因为着四年中,第一年就是一个闰年,所以如果剩下的日子小于366,那就按照闰年算出月和日,反之减去366,算出多了多少年,再算日期。

格里高利历(r>=2299162)

真正麻烦的是格里高利历。

格里高利历又多了“百年不闰,四百年再闰”的规则,于是我将400年作为一个周期,每400年97闰,那么每400年就要经过146097天。

总之,为了方便计算,先把r减去2299162。

因为格里高利历开始的时间是1582年的10月15日,如果在这个日期后,但在1582年里,就要分类讨论。而1582年10月15日距离1583年正好77天,这就有了77这个常数。

1583年前

这部分的处理简单粗暴,分成了三类,分别是10月,11月,12月。每类单独算日期。

1583年后(r>77)

我当时想着是直接快进到1600年,因为这一年正好是400的整倍数,可以作为一个周期的起点,但1583年并不是一个闰年,如果不把1600年之前的每4年组合在一起,将会十分难算。于是我打算将1584年作为一个节点。于是我将在1584年之后的日期和在这之前的日期分开计算。

而当时间快进到1584年时,就可以将剩下的16年以4年一组的形式划分,这样算到1600年。

1600年后

当到了1600后,剩下的事情就相对简单了。

首先将每146097年分成一组,这就是一个400年,首先计算出有多少个400年。

然后判断剩下的日子是否属于第一个百年,因为第一个一百年有25个闰年,而剩下的三个百年中,每一百年只有24个闰年,这也是常数36525的由来。

然后将4年确定为一个周期,确定在这100或300年中,这个日期属于哪个4年。

最后,在确定这个日期是平年或是闰年,分别算出月和日。

代码(看到最后有惊喜)

#include <cstdio>
#include <iostream>

long long q, r, day, month, year;
const int months[15]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monthr[15]={31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//const int julian=2297591;
const int julian=2299162;
int Month(), Monthr();

int main(){
	freopen("julian.in", "r", stdin);
	freopen("julian.out", "w", stdout);

	scanf("%lld", &q);
	for(int asdf=0; asdf<q; asdf++){
		scanf("%lld", &r);
		r++;
		if(r<julian){
			year=(r/1461)*4;
			r%=1461;
			if(r<=59){
				month=r>31?2:1;
				day=r>31?r-31:r;
			}
			else{
				if(r<=366){
					month=Monthr();
					day=r;
				}
				else{
					year+=(r-366)/365+1;
					r-=366; r%=365;
					month=Month();
					day=r;
				}
			}
			if(year<4713)
				if(day==0 && month==1)
					printf("31 12 %lld BC\n", 4713-year+1);
				else
					printf("%lld %lld %lld BC\n", day, month, 4713-year);
			else  
				if(day==0 && month==1)
					printf("31 12 %lld\n", year-4713);
				else
					printf("%lld %lld %lld\n", day, month, year-4713+1);
		}
		else{
			r-=julian;
			year=1582;
			if(r<=77){
				if(r<=16){ month=10; day=15+r; }
				else if(r<=46){ month=11; day=r-16; }
				else { month=12; day=r-46; }
			}
			else {
				r-=77;
				if(r<=365){
					year++;
					month=Month();
					day=r;
				}
				else{
					r-=365; year=1584;
					if(r<=5844) {
						year+=(r/1461)*4;
						r%=1461;
						if(r<=366){
							month=Monthr();
							day=r;
						}
						else {
							r-=366; year++;
							year+=r/365;
							r%=365;
							month=Month();
							day=r;
						}
					}
					else{
						r-=5844; year=1600;
						year+=(r/146097)*400;
						r%=146097;
						if(r<=36525){
							year+=(r/1461)*4;
							r%=1461;
							if(r<=366){ month=Monthr(); day=r; }
							else {
								r-=366; year++;
								year+=r/365; r%=365;
								month=Month(); day=r;
							}
						}
						else{
							r-=36525; year+=100;
							year+=(r/36524)*100;
							r%=36524;
							if(r<=1460){
								year+=r/365;
								r%=365;
								month=Month();
								day=r;
							}
							else{
								r-=1460; year+=4;
								year+=(r/1461)*4;
								r%=1461;
								if(r<=366) { month=Monthr(); day=r; }
								else{
									r-=366; year++;
									year+=r/365;
									r%=365;
									month=Month();
									day=r;
								}
							}
						}
					}
				}
			}
			if(day==0 && month==1)
				printf("31 12 %lld\n", year-1);
			else
				printf("%lld %lld %lld\n", day, month, year);
		}
//		printf("%d %d %d\n", day, month, year);
	}

	return 0;
}

int Month(){
	int i;
	for(i=0; i<12; i++){
		if(r>months[i]) r-=months[i];
		else break;
	}
	return i+1;
}
int Monthr(){
	int i;
	for(i=0; i<12; i++){
		if(r>monthr[i]) r-=monthr[i];
		else break;
	}
	return i+1;
}
/*
int Month(int x){
	if(0<x && x<=31) return 1;
	if(31<x && x<=59) return 2;
	if(59<x && x<=90) return 3;
	if(90<x && x<=120) return 4;
	if(120<x && x<=151) return 5;
	if(151<x && x<=181) return 6;
	if(181<x && x<=212) return 7;
	if(212<x && x<=243) return 8;
	if(243<x && x<=273) return 9;
	if(273<x && x<=304) return 10;
	if(304<x && x<=334) return 11;
	if(334<x && x<=365) return 12;
	if(0<x && x<=31) return 1;
}
int Monthr(int x){
	if(0<x && x<=31) return 1;
	if(31<x && x<=60) return 2;
	if(60<x && x<=91) return 3;
	if(91<x && x<=121) return 4;
	if(121<x && x<=152) return 5;
	if(152<x && x<=182) return 6;
	if(182<x && x<=213) return 7;
	if(213<x && x<=244) return 8;
	if(244<x && x<=274) return 9;
	if(274<x && x<=305) return 10;
	if(305<x && x<=335) return 11;
	if(335<x && x<=366) return 12;
	if(0<x && x<=31) return 1;
}*/

最后附上我算这些常数的过程(python控制台信息):

# ===== console log in CSP-S 2020 =====

noilinux@ubuntu:~/Desktop/SX-00019/julian$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:38) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()
noilinux@ubuntu:~/Desktop/SX-00019/julian$ python3
Python 3.4.0 (default, Apr 11 2014, 13:05:18) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 365*400+97
146097
>>> 4713*365
1720245
>>> 4713*365+1581*365
2297310
>>> 31+28+31+30+31+30+31+31+30+4
277
>>> 4713*365+1581*365+277+(4713%4+1)+(1582%4)
2297591
>>> 365*4+1
1461
>>> 365*3+31+28
1154
>>> 31+28
59
>>> 59+31
90
>>> 17+30+31
78
>>> 3000000-2297591
702409
>>> 702409-(16+30+31)
702332
>>> 4*(702332/1461)
1922.880219028063
>>> 4*(702332//1461)
1920
>>> 702332-4*1461
696488
>>> 702332-4*1920
694652
>>> 702332%1461
1052
>>> 1583+1920
3503
>>> 3501-1582
1919
>>> 3501-1583
1918
>>> 198/4
49.5
>>> 1918/4
479.5
>>> 1918*365+479
700549
>>> 700549+17+30+31
700627
>>> 3000000-700627
2299373
>>> 2299373-(31+28+31+30+31+30+31+15)
2299146
>>> 31+28+31+30+31+30+31+31+30+4+(1582+4713-1)*365
2297587
>>> (1582+4713-1)/4
1573.5
>>> 2297587+1573
2299160
>>> 3000000-2299160
700840
>>> 700840-77
700763
>>> 4*(700763//1461)
1916
>>> 1916*1461
2799276
>>> 700763%1461
944
>>> 700763-365
700398
>>> 700398//1461
479
>>> 4*479
1916
>>> 700398%1461
579
>>> 579-366
213
>>> 1916+1584+1
3501
>>> 365*4+1
1461
>>> 100*365+97
36597
>>> 1600-1584
16
>>> 16*365+4
5844
>>> 365*400+97
146097
>>> 100*365+25
36525
>>> 100*365+24
36524
>>> 365*4
1460
>>> 


posted @ 2020-11-10 19:06  TFLS-DJL  阅读(1371)  评论(0编辑  收藏  举报