[CSP-S2020] 儒略日
大模拟。
可以将时间分为 \(4\) 个部分:
- \(-4713.1.1\) 至 \(-1.12.31\)
- \(1.1.1\) 至 \(1582.10.4\)
- \(1582.10.5\) 至 \(1582.10.14\)
- \(1582.10.15\) 至无穷
大体可分为公元前(儒略历),公元后儒略历,公元后格里高利历。
如果 \(x\le 1721424\),说明是公元前儒略历,\(4\) 年一打包,其中 \(1\) 个闰年和 \(3\) 个平年,共 \(1461\) 天。然后按周期推年份。推完年份剩下的天数用来推月份,天数即可,注意判断闰年。
void bc(int x) {
int dY = x / zq1, i, op = 0; x %= zq1;
for (i = 0; i < 4; i++) {
if(i % 4 == 0 && x > 366) x -= 366;
else if(i % 4 != 0 && x > 365) x -= 365;
else break;
}
Y = 4713 - (dY * 4 + i);
if(x == 0) {
D = 31, M = 12;
Y++;
return ;
}
if(i == 0) op = 1;
for (i = 1; i <= 12; i++) {
int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
if(x > del) x -= del;
else break;
}
M = i;
D = x;
return ;
}
如果 \(1721424 < x \le 2299161\),说明是公元后儒略历,和公元前儒略历类似,不过多赘述。
void BBC(int x) {
int dY = x / zq1, i, op = 0; x %= zq1;
for (i = 1; i <= 4; i++) {
if(i % 4 == 0 && x > 366) x -= 366;
else if(i % 4 != 0 && x > 365) x -= 365;
else break;
}
Y = (dY * 4 + i);
if(x == 0) {
D = 31, M = 12;
Y--;
return ;
}
if(Y % 4 == 0) op = 1;
for (i = 1; i <= 12; i++) {
int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
if(x > del) x -= del;
else break;
}
M = i;
D = x;
return ;
}
然后是日期删除的部分,直接跳过\(1582.10.5\) 到 \(1582.10.15\) 日。然后进入到公元后格里高利历。由于 \(1582\) 年是从 \(10.15\) 开始的,所以要特判断掉这一年。到 \(1582.12.31\) 共 \(78\) 天。
if(x <= 78) {
if(x <= 17) {
M = 10, D = 15+x-1;
} else if(x <= 47) {
x -= 17;
M = 11, D = x;
} else {
x -= 47;
M = 12, D = x;
}
Y = 1582;
cout << D << ' ' << M << ' ' << Y << '\n';
return ;
}
然后按 \(400\) 年为一周期打包,一个周期有 \(97\) 个闰年和 \(303\) 个平年,共 \(97\times 366+303\times 365=146097\) 天。推完年份剩下的天数用来推月份,天数即可,注意判断闰年需要把 \(1582\) 年和包内的年份一起算上判断。
int dY = (x / y400), i, op = 0; x %= y400;
for (i = 1; i <= 400; i++) {
if(check(1582 + dY * 400 + i) && x > 366) x -= 366;
else if(!check(1582 + dY * 400 + i) && x > 365) x -= 365;
else break;
}
Y = 1582 + dY * 400 + i;
if(x == 0) {
M = 12, D = 31;
Y--;
goto ans2;
}
if(check(Y)) op = 1;
for (i = 1; i <= 12; i++) {
int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
if(x > del) x -= del;
else break;
}
M = i;
D = x;
ans2: cout << D << ' ' << M << ' ' << Y << '\n';
然后整合起来,分类讨论即可。
时间复杂度 \(O(q)\)。
#include<bits/stdc++.h>
#define int long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
using namespace std;
const int Mth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int zq1 = 1461, BC = 1721424, k1582 = 577737, y400 = 146097;
int q, x, D, M, Y;
bool check(int x) {
if(x % 400 == 0) return 1;
if(x % 4 == 0 && x % 100 != 0) return 1;
return 0;
}
void BBC(int x) {
int dY = x / zq1, i, op = 0; x %= zq1;
for (i = 1; i <= 4; i++) {
if(i % 4 == 0 && x > 366) x -= 366;
else if(i % 4 != 0 && x > 365) x -= 365;
else break;
}
Y = (dY * 4 + i);
if(x == 0) {
D = 31, M = 12;
Y--;
return ;
}
if(Y % 4 == 0) op = 1;
for (i = 1; i <= 12; i++) {
int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
if(x > del) x -= del;
else break;
}
M = i;
D = x;
return ;
}
void bc(int x) {
int dY = x / zq1, i, op = 0; x %= zq1;
for (i = 0; i < 4; i++) {
if(i % 4 == 0 && x > 366) x -= 366;
else if(i % 4 != 0 && x > 365) x -= 365;
else break;
}
Y = 4713 - (dY * 4 + i);
if(x == 0) {
D = 31, M = 12;
Y++;
return ;
}
if(i == 0) op = 1;
for (i = 1; i <= 12; i++) {
int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
if(x > del) x -= del;
else break;
}
M = i;
D = x;
return ;
}
void solve() {
D = M = Y = 0;
cin >> x; x++;
if(x <= BC) {
bc(x);
cout << D << ' ' << M << ' ' << Y << " BC\n";
} else {
x -= BC;
if(x <= k1582) {
BBC(x);
cout << D << ' ' << M << ' ' << Y << '\n';
} else {
x -= k1582;
if(x <= 78) {
if(x <= 17) {
M = 10, D = 15+x-1;
} else if(x <= 47) {
x -= 17;
M = 11, D = x;
} else {
x -= 47;
M = 12, D = x;
}
Y = 1582;
cout << D << ' ' << M << ' ' << Y << '\n';
return ;
}
x -= 78;
int dY = (x / y400), i, op = 0; x %= y400;
for (i = 1; i <= 400; i++) {
if(check(1582 + dY * 400 + i) && x > 366) x -= 366;
else if(!check(1582 + dY * 400 + i) && x > 365) x -= 365;
else break;
}
Y = 1582 + dY * 400 + i;
if(x == 0) {
M = 12, D = 31;
Y--;
goto ans2;
}
if(check(Y)) op = 1;
for (i = 1; i <= 12; i++) {
int del = ((op && i == 2) ? Mth[i] + 1 : Mth[i]);
if(x > del) x -= del;
else break;
}
M = i;
D = x;
ans2: cout << D << ' ' << M << ' ' << Y << '\n';
}
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(nullptr), cout.tie(nullptr);
cin >> q;
while(q--) solve();
return 0;
}
标签:真题,int,31,else,S2020,dY,366,365,CSP
From: https://www.cnblogs.com/Daniel-yao/p/18499136