70分,求大佬帮忙看看
#include <bits/stdc++.h>
using namespace std;
int yearr = 1582, monthh = 10, dayy = 15, dayys;
int perYear = 400;
#define int long long
struct Date {
int year, month, day;
inline void print() {
if (year < 0) {
printf("%lld %lld %lld BC\n", day, month, abs(year - 1));
} else {
printf("%lld %lld %lld\n", day, month, year);
}
}
inline bool isLeap(int yy) {
if (yy < yearr) {
return yy % 4 == 0;
}
return yy % 400 == 0 || (yy % 4 == 0 && yy % 100 != 0);
}
inline int getMonthDays(int yy, int mm) {
int ret;
switch (mm) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
ret = 31;
break;
case 4: case 6: case 9: case 11:
ret = 30;
break;
case 2 :
if (isLeap(yy)) {
ret = 29;
} else {
ret = 28;
}
break;
default:
assert(0);
}
if (yy == yearr && mm == 10) { // 对中间删除的日期单独处理
ret -= 10;
}
return ret;
}
inline int getYearDays(int yy) {
int ret = 365 + isLeap(yy);
if (yy == 1582) { // 对中间删除的日期单独处理
ret -= 10;
}
return ret;
}
inline int getJumpYearDays(int yy, int jumpyears) {
int ret = 0;
for (int i = 1; i <= jumpyears; ++i) {
ret += getYearDays(yy + i);
}
return ret;
}
};
int a[100001];
Date ans[100001];
inline bool cmp(int x, int y) {
return a[x] < a[y];
}
inline void solve(int n, int a[], Date ans[]) {
// BigJumpYear : 跳跃跨度400年
// JumpYear : 跳跃跨度1年
// JumpMonth : 跳跃跨度1个月
int BigJumpYear, JumpYear, JumpMonth;
int pos = 1; // 当前正在解决第几个询问
int ctr = 0; // 当前是第几个儒略日
int ord[100001]; // 各个询问从小到大排序后处理的顺序
Date cur; // 当前结果
BigJumpYear = cur.getJumpYearDays(yearr, perYear);
for (int i = 1; i <= n; ++i) {
ord[i] = i;
}
sort(ord + 1, ord + n + 1, cmp);
for (cur.year = -4712; pos <= n; ++cur.year) { // 枚举年份
// 此处是从公元前4712年开始是因为公元前1、5、9、...、4713年是闰年,所以按照公元后的闰年规则反推前面就会差一个闰年,所以从4712年开始反推
if (cur.year > yearr && ctr + BigJumpYear <= a[ord[pos]]) { //
cur.year += perYear;
cur.year--; // 由于for循环判断是只要pos != n 就自动再让cur.year + 1,所以这里要减去1,下面几处也是同理
ctr += BigJumpYear;
continue ;
}
JumpYear = cur.getYearDays(cur.year);
if (ctr + JumpYear <= a[ord[pos]]) {
ctr += JumpYear;
continue ;
}
for (cur.month = 1; cur.month <= 12; ++cur.month) { // 枚举月份
JumpMonth = cur.getMonthDays(cur.year, cur.month);
if (ctr + JumpMonth <= a[ord[pos]]) {
ctr += JumpMonth;
continue ;
}
bool flag;
if (JumpMonth == 21) { // 由于中间跳过了10天,所以1582年10月只有21天,这里使用一个标记判定这种情况
flag = 1;
} else {
flag = 0;
}
for (cur.day = 1; cur.day <= JumpMonth; ++cur.day) { // 枚举天数
while (ctr == a[ord[pos]] && pos <= n) {
ans[ord[pos]].year = cur.year;
ans[ord[pos]].month = cur.month;
ans[ord[pos]].day = cur.day;
pos++;
}
ctr++;
if (cur.day == 4 && flag) {
cur.day = 14;
}
}
}
}
}
signed main() {
freopen("bibi.in", "r", stdin);
freopen("bibi.out", "w", stdout);
int Q;
scanf("%lld", &Q);
for (int i = 1; i <= Q; ++i) {
scanf("%lld", &a[i]);
}
solve(Q, a, ans);
for (int i = 1; i <= Q; ++i) {
ans[i].print();
}
}