大家可以在洛谷提交:
題目描述
為了簡便計算,天文學家們使用儒略日(Julian day)來表達時間,所謂儒略日,其定義為從公元前 4713 年 1 月 1 日正午 12 點到此后某一時刻間所經過的天數,不滿一天者用小數表達,若利用這一天文學歷法,則每一個時刻都將被均勻的映射到數軸上,從而得以很方便的計算它們的差值,
現在,給定一個不含小數部分的儒略日,請你幫忙計算出該儒略日(一定是某一天的中午 12 點)所對應的公歷日期,
我們現行的公歷為格里高利歷(Gregorian calendar),它是在公元 1582 年由教皇格里高利十三世在原有的儒略歷(Julian calendar)的基礎上修改得到的(注:儒略歷與儒略日并無直接關系),具體而言,現行的公歷日期按照以下規則計算:
- 公元 1582 年 10 月 15 日(含)以后:適用格里高利歷,每年一月 3131 天、 二月 2828 天或 2929 天、三月 3131 天、四月 3030 天、五月 3131 天、六月 3030 天、七月 3131 天、八月 3131 天、九月 3030 天、十月 3131 天、十一月 3030 天、十二月 3131 天,其中,閏年的二月為 2929 天,平年為 2828 天,當年份是 400400 的倍數,或日期年份是 44 的倍數但不是 100100 的倍數時,該年為閏年,
- 公元 1582 年 10 月 5 日(含)至 10 月 14 日(含):不存在,這些日期被洗掉,該年 10 月 4 日之后為 10 月 15 日,
- 公元 1582 年 10 月 4 日(含)以前:適用儒略歷,每月天數與格里高利歷相同,但只要年份是 44 的倍數就是閏年,
- 盡管儒略歷于公元前 45 年才開始實行,且初期經過若干次調整,但今天人類習慣于按照儒略歷最終的規則反推一切 1582 年 10 月 4 日之前的時間,注意,公元零年并不存在,即公元前 1 年的下一年是公元 1 年,因此公元前 1 年、前 5 年、前 9 年、前 13 年……以此類推的年份應視為閏年,
輸入格式
第一行一個整數 QQ,表示詢問的組數,
接下來 QQ 行,每行一個非負整數 r_iri?,表示一個儒略日,
輸出格式
對于每一個儒略日 r_iri?,輸出一行表示日期的字串 s_isi?,共計 QQ 行, s_isi? 的格式如下:
- 若年份為公元后,輸出格式為
Day Month Year,其中日(Day)、月(Month)、年(Year)均不含前導零,中間用一個空格隔開,例如:公元 2020 年 11 月 7 日正午 12 點,輸出為7 11 2020, - 若年份為公元前,輸出格式為
Day Month Year BC,其中年(Year)輸出該年份的數值,其余與公元后相同,例如:公元前 841 年 2 月 1 日正午 12 點,輸出為1 2 841 BC,
輸入輸出樣例
輸入 #13 10 100 1000輸出 #1
11 1 4713 BC 10 4 4713 BC 27 9 4711 BC輸入 #2
3 2000000 3000000 4000000輸出 #2
14 9 763 15 8 3501 12 7 6239輸入 #3
見附件中的 julian/julian3.in輸出 #3
見附件中的 julian/julian3.ans
說明/提示
【資料范圍】
| 測驗點編號 | Q =Q= | r_i \leri?≤ |
|---|---|---|
| 11 | 10001000 | 365365 |
| 22 | 10001000 | 10^4104 |
| 33 | 10001000 | 10^5105 |
| 44 | 1000010000 | 3\times 10^53×105 |
| 55 | 1000010000 | 2.5\times 10^62.5×106 |
| 66 | 10^5105 | 2.5\times 10^62.5×106 |
| 77 | 10^5105 | 5\times 10^65×106 |
| 88 | 10^5105 | 10^7107 |
| 99 | 10^5105 | 10^9109 |
| 1010 | 10^5105 | 年份答案不超過 10^9109 |
附件下載:https://www.luogu.com.cn/fe/api/problem/downloadAttachment/4h186sh9
模擬思想,通過分類討論:
(1)-4713年到-1年;(n<=1721423)
(2)1年到1582年10月4日;(n>1721423&&n<=2299160)
(3)1582年10月15日;(n>2299160)
通過三個函式進行操作(跨年)+(跨月+跨日)
主要操作為年份,其中work函式將最后不足一年的天數和月數進行操作,
代碼實作如下:
1 void work(int &d,int &m,int &n,int p=0){
2 //從1.1往后跳n天并存在d與m中
3 //p=1/0表示是否為閏年
4 if(p) t[2]=29;
5 for(int i=1;i<=12;i++)
6 if(n>=t[i]) n-=t[i],m++;
7 else{
8 d+=n,t[2]=28;//將t[2]復原
9 return;
10 }
11 }
1 int t[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
其中t陣列存盤每個月的天數,
SOLVE1:
每四年為一閏年,則四年四年跳,當跳到只剩下不足四年時,就對n進行判斷:
1:不足一年,則為閏年,p=1,work();
2:超過一年,則一年一年跳,注意都不是閏年,到最后再work(),
void solve1(){
//1461=3*365+366
int d=1,m=1,y=-4713;
y+=n/1461*4,n%=1461;
if(n<366) work(d,m,n,1);//剩余n天,小于366為閏年
else{
n-=366,y++;
y+=n/365,n%=365;//加為平年
work(d,m,n);
}//y已經跳正確,
cout<<d<<" "<<m<<" "<<-y<<" BC"<<endl;
}
SOLVE2:
因為跳的天數大于公元前1年,則先減去公元前的天數再減去公元1年的第一天(),因為d(day)已經設為1.然后就四年四年跳,同上,(注意從這開始當n不足4年時,前三年為平年,最后一年為閏年)
1 void solve2()
2 {
3 int d=1,m=1,y=1;
4 n-=1721424;
5 y+=n/1461*4,n%=1461;//四年四年跳
6 //1095=3*365
7 if(n<1095){
8 //平年
9 y+=n/365,n%=365;
10 work(d,m,n);
11 }
12 else{
13 //閏年
14 n-=1095,y+=3;
15 work(d,m,n,1);
16 }
17 cout<<d<<" "<<m<<" "<<y<<endl;
18 }
SOLVE3:
從這開始就細節起來了,因為跳到了1582年10月15日,n-2299161;
第一種:答案就在1582年里,就直接討論剩下的三個月,
第二種:超過1582年,就先跳到1583.1.1,然后開始四百年四百年的跳,
跳到了不足四百年時又進行討論(注意到閏年的判斷條件變了)
1583年內%400==383,到四百四百跳完之后,到了不知道多少--83年時,則在(新的四百年)383到399年間、400年間、1到382年間討論,
383到399先四年四年跳,在對剩下不足四年進行操作,(注意前兩年會遇到閏年,后兩年為平年,
400年為閏年,直接操作,
1到382年先100年一百年跳,再四年四年跳,
1 void solve3()
2 {
3 int d=15,m=10,y=1582;//跳到1582.10.15
4 n-=2299161;
5 if(n<=77){
6 //答案在1582年中
7 if(n<=16)cout<<d+n<<" "<<m<<" "<<y<<endl;
8 else if(n<=46) cout<<n-16<<" "<<m+1<<" "<<y<<endl;
9 else cout<<n-46<<" "<<m+2<<" "<<y<<endl;
10 return;
11 }
12 n-=78,d=1,m=1,y=1583;//跳到1583.1.1
13 //146097=303*365+97*366//四百年中有97個閏年
14 y+=n/146097*400,n%=146097;//四百年四百年跳
15 /*
16 以下的年份從383開始,1583%400=383 ==> 不是閏年,則從383~399
17 、400、1~382三段進行跳(只剩下最后四百年沒跳了)
18 */
19 if(n<6209){
20 //6209=13*365+4*366(383~399)
21 y+=n/1461*4,n%=1461;//四年四年跳
22 if(n<365) work(d,m,n);
23 else if(n<731){
24 n-=365,y++;
25 work(d,m,n,1);
26 }
27 else{
28 n-=731,y+=2;
29 y+=n/365,n%=365;
30 work(d,m,n);
31 }
32 cout<<d<<" "<<m<<" "<<y<<endl;
33 }
34 else{
35 if(n<6575){
36 //6575=13*65+5*366,即0年
37 n-=6209,d=1,m=1,y+=17;
38 work(d,m,n,1);
39 cout<<d<<" "<<m<<" "<<y<<endl;
40 }
41 else{
42 //1~382
43 n-=6575,d=1,m=1,y+=18;
44 y+=n/36524*100,n%=36524;
45 //36524=76*365+24*366//一百年一百年跳
46 if(n<36159){
47 //36159=75*365+24*366(前99年)
48 y+=n/1461*4,n%=1461;
49 if(n<1095){
50 y+=n/365,n%=365;
51 work(d,m,n);
52 }
53 else{
54 n-=1095,y+=3;
55 work(d,m,n,1);
56 }
57 }
58 else{
59 //最后100年
60 n-=36159,y+=99;
61 work(d,m,n);//不是閏年
62 }
63 cout<<d<<" "<<m<<" "<<y<<endl;
64 }
65 }
66 }
總代碼:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define int long long 4 int q,r; 5 int n; 6 int t[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 7 void work(int &d,int &m,int &n,int p=0){ 8 //從1.1往后跳n天并存在d與m中 9 //p=1/0表示是否為閏年 10 if(p) t[2]=29; 11 for(int i=1;i<=12;i++) 12 if(n>=t[i]) n-=t[i],m++; 13 else{ 14 d+=n,t[2]=28;//將t[2]復原 15 return; 16 } 17 } 18 void solve1(){ 19 //1461=3*365+366 20 int d=1,m=1,y=-4713; 21 y+=n/1461*4,n%=1461; 22 if(n<366) work(d,m,n,1);//剩余n天,小于366為閏年 23 else{ 24 n-=366,y++; 25 y+=n/365,n%=365;//加為平年 26 work(d,m,n); 27 }//y已經跳正確, 28 cout<<d<<" "<<m<<" "<<-y<<" BC"<<endl; 29 } 30 void solve2() 31 { 32 int d=1,m=1,y=1; 33 n-=1721424; 34 y+=n/1461*4,n%=1461;//四年四年跳 35 //1095=3*365 36 if(n<1095){ 37 //平年 38 y+=n/365,n%=365; 39 work(d,m,n); 40 } 41 else{ 42 //閏年 43 n-=1095,y+=3; 44 work(d,m,n,1); 45 } 46 cout<<d<<" "<<m<<" "<<y<<endl; 47 } 48 void solve3() 49 { 50 int d=15,m=10,y=1582;//跳到1582.10.15 51 n-=2299161; 52 if(n<=77){ 53 //答案在1582年中 54 if(n<=16)cout<<d+n<<" "<<m<<" "<<y<<endl; 55 else if(n<=46) cout<<n-16<<" "<<m+1<<" "<<y<<endl; 56 else cout<<n-46<<" "<<m+2<<" "<<y<<endl; 57 return; 58 } 59 n-=78,d=1,m=1,y=1583;//跳到1583.1.1 60 //146097=303*365+97*366//四百年中有97個閏年 61 y+=n/146097*400,n%=146097;//四百年四百年跳 62 /* 63 以下的年份從383開始,1583%400=383 ==> 不是閏年,則從383~399 64 、400、1~382三段進行跳(只剩下最后四百年沒跳了) 65 */ 66 if(n<6209){ 67 //6209=13*365+4*366(383~399) 68 y+=n/1461*4,n%=1461;//四年四年跳 69 if(n<365) work(d,m,n); 70 else if(n<731){ 71 n-=365,y++; 72 work(d,m,n,1); 73 } 74 else{ 75 n-=731,y+=2; 76 y+=n/365,n%=365; 77 work(d,m,n); 78 } 79 cout<<d<<" "<<m<<" "<<y<<endl; 80 } 81 else{ 82 if(n<6575){ 83 //6575=13*65+5*366,即0年 84 n-=6209,d=1,m=1,y+=17; 85 work(d,m,n,1); 86 cout<<d<<" "<<m<<" "<<y<<endl; 87 } 88 else{ 89 //1~382 90 n-=6575,d=1,m=1,y+=18; 91 y+=n/36524*100,n%=36524; 92 //36524=76*365+24*366//一百年一百年跳 93 if(n<36159){ 94 //36159=75*365+24*366(前99年) 95 y+=n/1461*4,n%=1461; 96 if(n<1095){ 97 y+=n/365,n%=365; 98 work(d,m,n); 99 } 100 else{ 101 n-=1095,y+=3; 102 work(d,m,n,1); 103 } 104 } 105 else{ 106 //最后100年 107 n-=36159,y+=99; 108 work(d,m,n);//不是閏年 109 } 110 cout<<d<<" "<<m<<" "<<y<<endl; 111 } 112 } 113 } 114 signed main() 115 { 116 //freopen("julian.in","r",stdin); 117 //freopen("julian.out","w",stdout); 118 cin>>q; 119 for(int i=1;i<=q;i++) 120 { 121 cin>>r; 122 n=r; 123 if(n<=1721423) solve1(); 124 if(r>1721423&&r<=2299160) solve2(); 125 if(r>2299160) solve3(); 126 } 127 return 0; 128 }
以上來源于SCDN的weixin_45429627+個人理解,
感謝各位來到我的博客園,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/349468.html
標籤:C++
上一篇:如何在aspnetcorewebAPI上正確地將串列轉換為IQueryable
下一篇:2021.11.4測驗T1-妹子
