謹以此篇題解,紀念我那炸掉的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
>>>