Solution
大毒瘤模拟,出题人我日你马。
以后考场上遇到大模拟,一定不要着急,选择最简单最好写的代码,三思而后行。如果没有把握可以先写部分分,说不定后面的题更简单。
在纸上列一下需要注意的地方,写代码时分步调试
-
闰年的计算法则,这个需要写一个函数 [ l , r ] [l,r] [l,r] 求 [ l , r ] [l,r] [l,r] 之间有多少个闰年。
-
缺失的十天,加上这十天会不会出现进位。
-
数据范围较大,不能模拟,可以循环节或二分。
-
分段处理,端点问题。
可惜我对于缺失的十天处理时出现了一点疏忽,导致考场卡在 1582 年的数据会少算 10 10 10 天,因为时间原因没有发现。
改动三行后 AC 的代码
Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 0x3f3f3f3f;
int get1(int r) {
if (r == 0) return 0;
return 1 + (r - 1) / 4;
}
int get(int r) {
if (r == 0) return 0;
return r / 4;
}
int get2(int r) {
return (r / 4) - (r / 100) + (r / 400);
}
int getrun(int l, int r, bool typ) {
if (l > r) return 0;
l--;
if (typ == 0) return get1(r) - get1(l);
if (l > 1582) return get2(r) - get2(l);
if (r <= 1582) return get(r) - get(l);
return get(1582) - get(l) + get2(r) - get2(1582);
}
bool check(int d) {
if (d % 400 == 0 || (d % 4 == 0 && d % 100 != 0)) return 1;
return 0;
}
int day[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, INF};
signed main() {
int Q; scanf("%lld", &Q);
while (Q--) {
int r; scanf("%lld", &r);
int y = 4713, m = 1, d = 1;
int L = 0, R = 4713, add = 0;
while (L <= R) {
int mid = (L + R) >> 1;
int sto = r - mid * 365 - getrun(4713 - mid + 1, 4713, 0);
if (sto >= 0) L = mid + 1, add = mid;
else R = mid - 1;
}
y -= add;
int orz = r - add * 365 - getrun(4713 - add + 1, 4713, 0);
if (y >= 1) {
if (getrun(y, y, 0) == 1) day[2]++;
int now = 1;
while (orz >= day[now]) {
orz -= day[now];
m++, now++;
}
d += orz;
if (getrun(y, y, 0) == 1) day[2]--;
printf("%lld %lld %lld BC\n", d, m, y);
}
else {
y = 1; r = orz;
L = 0, R = 1e9, add = 0;
while (L <= R) {
int mid = (L + R) >> 1;
int sto = r - mid * 365 - getrun(1, mid, 1);
if (sto >= 0) L = mid + 1, add = mid;
else R = mid - 1;
}
orz = r - add * 365 - getrun(1, add, 1);
y += add;
if (getrun(y, y, 1) == 1) day[2]++;
int now = 1, sto = orz;
while (sto >= day[now]) {
sto -= day[now];
m++, now++;
}
if (getrun(y, y, 1) == 1) day[2]--;
if (y > 1582) orz += 10;
else if (y == 1582 && m > 10) orz += 10;
else if (y == 1582 && m == 10 && d + sto >= 5) orz += 10;
if (getrun(y, y, 1) == 1) {
if (orz > 365) orz %= 365, y++, orz--;
}
else if (orz > 364) orz %= 364, y++, orz--;
if (getrun(y, y, 1) == 1) day[2]++;
now = 1; m = 1;
while (orz >= day[now]) {
orz -= day[now];
m++, now++;
}
d += orz;
if (getrun(y, y, 1) == 1) day[2]--;
printf("%lld %lld %lld\n", d, m, y);
}
}
return 0;
}