[AOJ] No. 0261 マヤの大予言
問題
方針
時刻の変換と同じように、いったん最小単位に変換してから計算を行います。西暦からマヤ歴への変換は、2012年12月21日からどれだけの日数が経過したかどうかを計算します。このときうるう日に気を付けます。マヤ歴から西暦への変換は、西暦の年数を二分探索によって求めます。
コード
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll mod = 1872000; ll day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; ll todays(ll y, ll m, ll d) { ll ret = (y - 1) * 365 + (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 + d; if ((y % 4 == 0 && y % 100 != 0) ||( y % 400 == 0)) { if (m > 2) ret++; } for (int i = 0; i < m - 1; i++) { ret += day[i]; } return ret; } void stom(ll y, ll m, ll d) { ll a[5]{}; a[4] = 1; a[3] = 20; a[2] = a[3] * 18; a[1] = a[2] * 20; a[0] = a[1] * 20; ll t = todays(y, m, d) - todays(2012, 12, 21); t %= mod; ll c[5]{}; c[0] = t / a[0]; c[1] = (t - c[0] * a[0]) / a[1]; c[2] = (t - c[0] * a[0] - c[1] * a[1]) / a[2]; c[3] = (t - c[0] * a[0] - c[1] * a[1] - c[2] * a[2]) / a[3]; c[4] = t - c[0] * a[0] - c[1] * a[1] - c[2] * a[2] - c[3] * a[3]; for (int i = 0; i < 5; i++) { if (i == 4) { cout << c[i] << "\n"; } else { cout << c[i] << "."; } } } void mtos(ll b, ll ka, ll t, ll w, ll ki) { ll f = b * 20 * 20 * 18 * 20; f += ka * 20 * 18 * 20; f += t * 20 * 18; f += w * 20 + ki; f += todays(2012, 12, 21); ll l = -1; ll r = 100000000; while (r - l > 1) { ll m = (l + r) / 2; if (todays(m, 1, 1) <= f) { l = m; } else { r = m; } } ll y = l; ll m = 1; f -= todays(y - 1, 12, 31); for (int i = 0; i < 12; i++) { int g = day[i]; if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) { if (i == 1) g = 29; } if (f - g <= 0) { m = i + 1; break; } else { f -= g; } } cout << y << "." << m << "." << f << "\n"; } int main() { string s; cin >> s; while (s != "#") { vector<ll> v; string t = ""; for (int i = 0; i < s.length(); i++) { if (s[i] == '.') { v.push_back(stoi(t)); t = ""; } else if (i == s.length() - 1) { t += s[i]; v.push_back(stoi(t)); } else { t += s[i]; } } if (v.size() == 3) { stom(v[0], v[1], v[2]); } else { mtos(v[0], v[1], v[2], v[3], v[4]); } cin >> s; } return 0; }
ディスカッション
コメント一覧
まだ、コメントがありません