洛谷:P7075
OJ:CSPS2020A
算法逻辑:
year = 0
。year
转换为正数,并加上 “BC” 标识。int left = -4712, right = 1e9 + 5;
calculate_total_days(year) >= julian_day
的最小年份 year
。julian_day
,计算在该年份内的天数:julian_day -= calculate_total_days(year - 1);
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | /**************************************************************** * Description: 2020提高组复赛第一题 儒略日 * Author: Alex Li * Date: 2024-09-29 17:20:51 * LastEditTime: 2024-09-29 18:51:10 ****************************************************************/ #include <iostream> using namespace std; typedef long long LL; // 每个月的天数数组,初始为平年(非闰年)的天数 int days_in_month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 计算从起始年份到指定年份之间的总天数 LL calculate_total_days(LL year) { int start_year = -4712; // 起始年份(公元前4713年,因为没有公元0年) if (year < start_year) return 0; // 按每年365天计算初始总天数 LL total_days = (year - start_year + 1) * 365; if (year < 1582) { // 儒略历闰年,每4年一个闰年 total_days += (year - start_year) / 4 + 1; } else { // 格里高利历的调整 total_days -= 10; // 调整1582年10月5日至14日缺失的10天 // 计算从起始年份到1581年的闰年天数(儒略历规则) total_days += (1581 - start_year) / 4 + 1; // 计算1582年之后的闰年天数(格里高利历规则) total_days += (year - 1580) / 4 - (year - 1500) / 100 + (year - 1200) / 400; } return total_days; } // 判断指定年份是否为闰年 bool is_leap_year(int year) { if (year > 1582) { // 格里高利历闰年规则:能被4整除且不能被100整除,或能被400整除 return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } else { // 儒略历闰年规则:能被4整除 return year % 4 == 0; } } int main() { freopen("julian.in","r",stdin); freopen("julian.out","w",stdout); int query_count; cin >> query_count; while (query_count--) { LL julian_day; cin >> julian_day; julian_day++; // 将儒略日调整为从1开始计数 // 二分查找年份,使得calculate_total_days(year) >= julian_day int left = -4712, right = 1e9 + 5; while (left < right) { int mid = (left + right) >> 1; if (calculate_total_days(mid) >= julian_day) { right = mid; } else { left = mid + 1; } } int year = left; // 找到对应的年份 julian_day -= calculate_total_days(year - 1); // 计算该年份内的天数 // 更新当前年份二月的天数,考虑闰年 days_in_month[2] = 28 + is_leap_year(year); // 处理1582年10月的特殊情况(缺少10天) days_in_month[10] = (year == 1582) ? 21 : 31; int month; // 遍历月份,找到对应的月份 for (int i = 1; i <= 12; i++) { if (julian_day > days_in_month[i]) { julian_day -= days_in_month[i]; } else { month = i; break; } } int day = julian_day; // 剩余的天数即为日期 // 处理1582年10月5日至14日不存在的日期 if (year == 1582 && month == 10) { if (day >= 5) day += 10; // 跳过缺失的日期 cout << day << " " << month << " " << year << endl; } else { if (year > 0) cout << day << " " << month << " " << year << endl; else cout << day << " " << month << " " << -year + 1 << " BC" << endl; // 公元前年份处理 } } return 0; } |