CSP-S 2020 儒略日
模拟,二分
实际上现在感觉并不难(以前的因为 UOJ 上的 Hack 数据没过,所以重写了)。
对于 \(1582\) 年(含)以前的日期并不多,可以一年一年的枚举处理,这部分是最麻烦的部分,并不需要优化。剩下的就是 \(1583\) 年(含)往后的日期了,可以用二分优化,这部分并不难算,因为都是公历。时间复杂度为 \(O(\log w)\)。
#include <bits/stdc++.h>
typedef long long LL;
const int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void print(int o, int x, int y) {
if (o == 0) {
for (int i = 1; i <= 12; i++) {
int t = month[i] + (i == 2 && (y - 1) % 4 == 0);
if (x <= t) {
std::cout << x << ' ' << i << ' ' << y << " BC" << '\n';
return;
}
x -= t;
}
} else if (o == 1) {
for (int i = 1; i <= 12; i++) {
int t = month[i] + (i == 2 && y % 4 == 0);
if (x <= t) {
std::cout << x << ' ' << i << ' ' << y << '\n';
return;
}
x -= t;
}
} else {
for (int i = 1; i <= 12; i++) {
int t = month[i];
if (i == 2 && ((y % 100 != 0 && y % 4 == 0) || y % 400 == 0)) t++;
if (x <= t) {
std::cout << x << ' ' << i << ' ' << y << '\n';
return;
}
x -= t;
}
}
}
LL calc(int n) {
LL res = 1ll * (n - 1582) * 365;
if (n >= 1584) res += 1 + (n - 1584) / 4;
if (n >= 1600) res -= (n - 1600) / 100, res += (n - 1600) / 400;
return res;
}
void solve() {
LL x;
std::cin >> x;
for (int i = 1; i <= 12; i++) {
int t = month[i] - (i == 1) + (i == 2);
if (x <= t) {
std::cout << x + (i == 1) << ' ' << i << ' ' << "4713 BC" << '\n';
return;
}
x -= t;
}
for (int i = 4712; i >= 1; i--) {
int t = 365 + ((i - 1) % 4 == 0);
if (x <= t) return print(0, x, i);
x -= t;
}
for (int i = 1; i <= 1581; i++) {
int t = 365 + (i % 4 == 0);
if (x <= t) return print(1, x, i);
x -= t;
}
for (int i = 1; i <= 12; i++) {
int t = month[i];
if (i == 10) {
t -= 10;
if (x <= t) {
if (x > 4) x += 10;
std::cout << x << ' ' << i << ' ' << 1582 << '\n';
return;
}
x -= t;
continue;
}
if (x <= t) {
std::cout << x << ' ' << i << ' ' << 1582 << '\n';
return;
}
x -= t;
}
int l = 1583, r = 1e9, ans = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (calc(mid) < x) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
if (!ans) {
print(2, x, 1583);
return;
}
x -= calc(ans);
print(2, x, ans + 1);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int q;
std::cin >> q;
while (q--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号