CSP-S 2020 儒略日

模拟,二分

实际上现在感觉并不难(以前的因为 UOJ 上的 Hack 数据没过,所以重写了)。

对于 \(1582\) 年(含)以前的日期并不多,可以一年一年的枚举处理,这部分是最麻烦的部分,并不需要优化。剩下的就是 \(1583\) 年(含)往后的日期了,可以用二分优化,这部分并不难算,因为都是公历。时间复杂度为 \(O(\log w)\)

#include <bits/stdc++.h>

typedef long long LL;
const int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

void print(int o, int x, int y) {
  if (o == 0) {
    for (int i = 1; i <= 12; i++) {
      int t = month[i] + (i == 2 && (y - 1) % 4 == 0);
      if (x <= t) {
        std::cout << x << ' ' << i << ' ' << y << " BC" << '\n';
        return;
      }
      x -= t;
    }
  } else if (o == 1) {
    for (int i = 1; i <= 12; i++) {
      int t = month[i] + (i == 2 && y % 4 == 0);
      if (x <= t) {
        std::cout << x << ' ' << i << ' ' << y << '\n';
        return;
      }
      x -= t;
    }
  } else {
    for (int i = 1; i <= 12; i++) {
      int t = month[i];
      if (i == 2 && ((y % 100 != 0 && y % 4 == 0) || y % 400 == 0)) t++;
      if (x <= t) {
        std::cout << x << ' ' << i << ' ' << y << '\n';
        return;
      }
      x -= t;
    }
  }
}

LL calc(int n) {
  LL res = 1ll * (n - 1582) * 365;
  if (n >= 1584) res += 1 + (n - 1584) / 4;
  if (n >= 1600) res -= (n - 1600) / 100, res += (n - 1600) / 400;
  return res;
}

void solve() {
  LL x;
  std::cin >> x;
  for (int i = 1; i <= 12; i++) {
    int t = month[i] - (i == 1) + (i == 2);
    if (x <= t) {
      std::cout << x + (i == 1) << ' ' << i << ' ' << "4713 BC" << '\n';
      return;
    }
    x -= t;
  }
  for (int i = 4712; i >= 1; i--) {
    int t = 365 + ((i - 1) % 4 == 0);
    if (x <= t) return print(0, x, i);
    x -= t;
  }
  for (int i = 1; i <= 1581; i++) {
    int t = 365 + (i % 4 == 0);
    if (x <= t) return print(1, x, i);
    x -= t;
  }
  for (int i = 1; i <= 12; i++) {
    int t = month[i];
    if (i == 10) {
      t -= 10;
      if (x <= t) {
        if (x > 4) x += 10;
        std::cout << x << ' ' << i << ' ' << 1582 << '\n';
        return;
      }
      x -= t;
      continue;
    }
    if (x <= t) {
      std::cout << x << ' ' << i << ' ' << 1582 << '\n';
      return;
    }
    x -= t;
  }
  int l = 1583, r = 1e9, ans = 0;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (calc(mid) < x) {
      ans = mid;
      l = mid + 1;
    } else {
      r = mid - 1;
    }
  }
  if (!ans) {
    print(2, x, 1583);
    return;
  }
  x -= calc(ans);
  print(2, x, ans + 1);
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  int q;
  std::cin >> q;
  while (q--) {
    solve();
  }
  return 0;
}
posted @ 2024-10-09 23:43  Unino  阅读(11)  评论(0)    收藏  举报