AOJ 0261 Mayan Crucial Prediction
訳
日本語なので省略
解説
- マヤ暦→西暦
最大でも2016000日を処理するので愚直にループを回せばいける。
あと((((b*20+ka)*20+t)*18+w)*20+ki)とかで求めようとするとバグ埋め込む原因になった(自分の場合は)
- 西暦→マヤ暦
先に閏年を求めるのでy-2013回ループを回すことになるが、その後は年月日を日数に変換するのにO(1)だしだいたい後の処理も定数がついたO(1)なので大丈夫。
ただオーバーフローに気をつけないと自分みたいにかなり時間を取られる…(糞雑魚)
コード
char s[16]; int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; bool leapYear(int y) { return (!(y % 4) && (y % 100)) || !(y % 400); } char ret[32]; string MayanToAD(void) { long long b, ka, t, w, ki, y, m, d; sscanf(s, "%lld.%lld.%lld.%lld.%lld", &b, &ka, &t, &w, &ki); long long dki = b * 144000 + ka * 7200 + t * 360 + w * 20 + ki; if(dki <= 10) y = 2012, m = 12, d = 21 + dki; else { dki -= 10; for(int yy = 2013; ; yy++) { for(int mm = 1; mm <= 12; mm++) { int tmp = (leapYear(yy) && mm == 2); for(int dd = 1; dd <= (month[mm] + tmp); dd++) { dki--; if(dki == 0) { y = yy; m = mm; d = dd; goto end; } } } } } end:; sprintf(ret, "%lld.%lld.%lld", y, m, d); return ret; } string ADToMayan(void) { long long y, m, d, b, ka, t, w, ki; int leap = 0; sscanf(s, "%lld.%lld.%lld", &y, &m, &d); for(int i = 2013; i < y; i++) if(leapYear(i)) leap++; if(leapYear(y) && m > 2) leap++; long long dy = 365 * (y - 2013 <= 0 ? 0 : y - 2013) + leap; if(y > 2012) { dy += 10; for(int i = 1; i <= m; i++) if(i == m) dy += d; else dy += month[i]; } else dy = d - 21; dy %= 1872000; b = dy / 144000; dy %= 144000; ka = dy / 7200; dy %= 7200; t = dy / 360; dy %= 360; w = dy / 20; dy %= 20; ki = dy; sprintf(ret, "%lld.%lld.%lld.%lld.%lld", b, ka, t, w, ki); return ret; } int main() { string ans; while(cin >> s) { if(s[0] == '#') break; int dn = 0; for(int i = 0; i < strlen(s); i++) if(s[i] == '.') dn++; if(dn == 2) ans = ADToMayan(); else ans = MayanToAD(); cout << ans << endl; } }
閏年もO(1)で求めれるらしい…
経過日数の計算 (アルゴリズムとデータ構造)