From f8b4831d7bf95a44dac9c93edaee44459ba4b4cc Mon Sep 17 00:00:00 2001 From: Zengtudor Date: Tue, 23 Sep 2025 15:51:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7=E6=AF=94=E8=BE=83=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=97=A5=E6=9C=9F=E8=AE=A1=E7=AE=97=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现版本号比较功能,新增 compare-version-numbers.cpp 文件。同时重构 P7075.cpp 中的日期计算逻辑,优化闰年判断和日期转换算法,提高代码可读性和准确性。 --- src/9/22/P7075.cpp | 209 +++++++++++++++++++++++---- src/9/23/compare-version-numbers.cpp | 67 +++++++++ 2 files changed, 248 insertions(+), 28 deletions(-) create mode 100644 src/9/23/compare-version-numbers.cpp diff --git a/src/9/22/P7075.cpp b/src/9/22/P7075.cpp index d986125..8a67367 100644 --- a/src/9/22/P7075.cpp +++ b/src/9/22/P7075.cpp @@ -1,37 +1,190 @@ -#include #include -#include -#include -using ll = int64_t; +#include +#include -const ll af = 400*365+97; -const ll bf = 400*365+100; +// 使用 long long 防止在计算天数和年份时溢出 +using ll = long long; -const ll l = 2299160; +// 公元后每月天数(非闰年) +const int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -struct Day{ - ll d,m,y; -}; +// 预计算一些关键时间点的儒略日数值 +// 公元 1 年 1 月 1 日对应的儒略日 (r) +const ll R_AD_START = 1721424; // (4713 - 1) * 365 + (4713 - 1) / 4 = 1721423. r=0 是第一天,所以第1721424天是公元1年1月1日 +// 公元 1582 年 10 月 5 日对应的儒略日 +const ll R_GREGORIAN_START = 2299161; // 这是被删除的10天的第一天 -std::map m; - -static inline void solve(ll n){ - if(n<=l){ - - }else{ - - } +// 判断公元后年份是否为儒略历闰年 +bool is_julian_leap(ll year) { + return year % 4 == 0; } -int main(){ - std::iostream::sync_with_stdio(false); - std::cin.tie(nullptr); +// 判断公元后年份是否为格里高利历闰年 +bool is_gregorian_leap(ll year) { + return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); +} - ll Q; - std::cin>>Q; - while(Q--){ - ll r; - std::cin>>r; - solve(r); +// 解决单个查询的函数 +void solve() { + ll r; + std::cin >> r; + + // 阶段一:处理公元前日期 + if (r < R_AD_START) { + // 从公元前4713年开始 + ll year = 4713; + // +1 是因为 r=0 是第一天 + ll days_left = r + 1; + + // 逐年减去天数来确定年份 + while (true) { + bool is_bc_leap = (year % 4 == 1); // 公元前闰年规则 + int year_days = 365 + (is_bc_leap ? 1 : 0); + if (days_left <= year_days) { + break; // 找到了年份 + } + days_left -= year_days; + year--; + } + + // 在年内确定月份和日期 + int month = 1; + bool is_bc_leap = (year % 4 == 1); + while (true) { + int month_days = days_in_month[month]; + if (month == 2 && is_bc_leap) { + month_days = 29; + } + if (days_left <= month_days) { + break; // 找到了月份 + } + days_left -= month_days; + month++; + } + + std::cout << days_left << " " << month << " " << year << " BC\n"; + return; } -} \ No newline at end of file + + // 如果 r >= R_AD_START,说明是公元后日期 + // 将 r 转换为相对于公元 1 年 1 月 1 日的天数 + ll days_since_ad = r - R_AD_START + 1; + ll year = 1; + + // 阶段二:处理儒略历的公元后时期 (直到 1582 年 10 月 4 日) + if (r < R_GREGORIAN_START) { + // 逐年逼近 + while (true) { + int year_days = 365 + (is_julian_leap(year) ? 1 : 0); + if (days_since_ad <= year_days) { + break; + } + days_since_ad -= year_days; + year++; + } + + // 年内确定月日 + int month = 1; + while (true) { + int month_days = days_in_month[month]; + if (month == 2 && is_julian_leap(year)) { + month_days = 29; + } + // 特殊处理 1582 年 10 月 + if (year == 1582 && month == 10) { + // r < R_GREGORIAN_START 保证了日期在4号或之前 + // 此时 days_since_ad 就是当月的日期 + break; + } + if (days_since_ad <= month_days) { + break; + } + days_since_ad -= month_days; + month++; + } + + std::cout << days_since_ad << " " << month << " " << year << "\n"; + return; + } + + // 阶段三:处理格里高利历时期 (1582 年 10 月 15 日及以后) + // 从 1582 年 10 月 15 日开始计算 + days_since_ad = r - R_GREGORIAN_START + 1; + year = 1582; + int month = 10; + ll day = 15; + + // 先减去 1582 年剩余的天数 + ll remaining_days_1582 = 31 - 15 + 1 + 30 + 31; // 10, 11, 12 月 + if (days_since_ad <= remaining_days_1582) { + days_since_ad += 14; // 补偿回15号之前的日子,方便计算 + while(true){ + int month_days = days_in_month[month]; + if(days_since_ad <= month_days){ + day = days_since_ad; + break; + } + days_since_ad -= month_days; + month++; + } + std::cout << day << " " << month << " " << year << "\n"; + return; + } + + days_since_ad -= remaining_days_1582; + year = 1583; + + // 格里高利历的400年周期天数:400*365 + 97 = 146097 + const ll GREGORIAN_CYCLE_DAYS = 146097; + ll num_cycles = days_since_ad / GREGORIAN_CYCLE_DAYS; + year += num_cycles * 400; + days_since_ad %= GREGORIAN_CYCLE_DAYS; + + // 如果 days_since_ad 为 0, 说明是上一个周期的最后一天,需要回退 + if (days_since_ad == 0) { + year -= 400; + // 一个周期正好是146097天,所以回退后是这一大周期的最后一天 + days_since_ad = GREGORIAN_CYCLE_DAYS; + } + + // 在剩余的小于400年的周期内,逐年确定年份 + while (true) { + int year_days = 365 + (is_gregorian_leap(year) ? 1 : 0); + if (days_since_ad <= year_days) { + break; + } + days_since_ad -= year_days; + year++; + } + + // 年内确定月日 + month = 1; + while (true) { + int month_days = days_in_month[month]; + if (month == 2 && is_gregorian_leap(year)) { + month_days = 29; + } + if (days_since_ad <= month_days) { + break; + } + days_since_ad -= month_days; + month++; + } + day = days_since_ad; + + std::cout << day << " " << month << " " << year << "\n"; +} + +int main() { + // OI/ACM 风格的快速 IO + std::ios_base::sync_with_stdio(false); + std::cin.tie(NULL); + + int Q; + std::cin >> Q; + while (Q--) { + solve(); + } + + return 0; +} diff --git a/src/9/23/compare-version-numbers.cpp b/src/9/23/compare-version-numbers.cpp new file mode 100644 index 0000000..ed8c3bb --- /dev/null +++ b/src/9/23/compare-version-numbers.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +using namespace std; + + +class Solution { +public: + struct Version{ + vector v; + inline int operator[](int n)const{ + if(nother[i]){ + return false; + } + } + return false; + } + inline bool operator==(const Version&other)const{ + for(int i=0;i