65020 - [CSP-S2020] 儒略日 julian

解题思路

在题目这种历法中,日期计算以400年为周期,每400年都有恰好146097天。

我们可以预处理出400年内的情况,将年份模400即可快速得到答案。

加速技巧

对于“格里高利历”,以1200年1月1日为起始日,r减去2159351天 r⩽2299160即为儒略历。公元前x年视为(1-x)年。

参考代码

#include <bits/stdc++.h>
using namespace std;
const int N = 146097, A = 2299160, B = 2159351, C = 1461, D = 4712;
int y[N], m[N], d[N];
inline int get(int y, int m) {
    if (m == 2) {
		return (y % 4) ? 28 : (y % 100) ? 29 : y % 400 ? 28 : 29;
	}
    return (m == 4 || m == 6 || m == 9 || m == 11) ? 30 : 31;
}
void init() {
	m[0] = d[0] = 1;
    for(int i = 1; i < N; ++i) {
        d[i] = d[i - 1] + 1; m[i] = m[i - 1]; y[i] = y[i - 1];
        if (d[i] > get(y[i], m[i])) {
			++m[i]; d[i] = 1;
		}
        if (m[i] > 12) {
			++y[i]; m[i] = 1;
		} 
    }
}
int main() {
	init();
    int T; cin >> T;
    while (T--) {
        long long n, t; cin >> n;
        if (n > A) {
            n -= B; t = n / N * 400 + 1200; n %= N;
        } else {
            t = n / C * 4 - D; n %= C;
        }
        if (t + y[n] > 0) {
        	cout << d[n] << ' ' << m[n] << ' ' << t + y[n] << '\n';
        } else {
        	cout << d[n] << ' ' << m[n] << ' ' << 1 - t - y[n] << " BC\n";
        }
    }
    return 0;
}