• 「题解」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
    ", 4713-year+1);
    				else
    					printf("%lld %lld %lld BC
    ", day, month, 4713-year);
    			else  
    				if(day==0 && month==1)
    					printf("31 12 %lld
    ", year-4713);
    				else
    					printf("%lld %lld %lld
    ", 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
    ", year-1);
    			else
    				printf("%lld %lld %lld
    ", day, month, year);
    		}
    //		printf("%d %d %d
    ", 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
    >>> 
    
    
    
  • 相关阅读:
    TPM 程序设计基础 2-1 :具体函数调用步骤及解析示例
    TPM 程序设计基础 1-2-4 :新的 PCR 命令
    TPM 程序设计基础 1-2-3 :Tspi_PcrComposite 类定义
    TPM 程序设计基础 1-2-2 :旧的 PCR 命令
    TPM 程序设计基础 1-2-1 :Tspi_Context 类定义
    TPM 程序设计基础 1-1 :所用 Tspi 函数目录
    TPM 程序设计基础 0-0 :课设程序结构说明
    TPM 课设程序运行基础与要求
    jstl和EL表达式混合使用
    在eclipse中从cvs下载项目,再部署到tomcat常见错误!
  • 原文地址:https://www.cnblogs.com/dong628/p/13955460.html
Copyright © 2020-2023  润新知