mirror of
https://gitcode.com/Zengtudor/alg2025.git
synced 2025-11-09 16:12:21 +00:00
feat: 添加版本号比较功能并优化日期计算逻辑
实现版本号比较功能,新增 compare-version-numbers.cpp 文件。同时重构 P7075.cpp 中的日期计算逻辑,优化闰年判断和日期转换算法,提高代码可读性和准确性。
This commit is contained in:
parent
e4225e6f1a
commit
f8b4831d7b
@ -1,37 +1,190 @@
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <map>
|
||||
using ll = int64_t;
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
|
||||
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<ll, Day> 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);
|
||||
|
||||
ll Q;
|
||||
std::cin>>Q;
|
||||
while(Q--){
|
||||
ll r;
|
||||
std::cin>>r;
|
||||
solve(r);
|
||||
}
|
||||
// 判断公元后年份是否为格里高利历闰年
|
||||
bool is_gregorian_leap(ll year) {
|
||||
return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
|
||||
}
|
||||
|
||||
// 解决单个查询的函数
|
||||
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;
|
||||
}
|
||||
|
||||
// 如果 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;
|
||||
}
|
||||
67
src/9/23/compare-version-numbers.cpp
Normal file
67
src/9/23/compare-version-numbers.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
struct Version{
|
||||
vector<int> v;
|
||||
inline int operator[](int n)const{
|
||||
if(n<v.size()){
|
||||
return v[n];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
inline Version(const string &str){
|
||||
int p=0;
|
||||
for(int i=0;i<str.size();i++){
|
||||
if(str[i]=='.'){
|
||||
v.push_back(
|
||||
atoi(str.substr(p,i-p).c_str())
|
||||
);
|
||||
p=i+1;
|
||||
}
|
||||
}
|
||||
v.push_back(
|
||||
atoi(str.substr(p).c_str())
|
||||
);
|
||||
for(auto i:v){
|
||||
printf("%d ",i);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
inline bool operator<(const Version&other)const{
|
||||
for(int i=0;i<max(v.size(),other.v.size());i++){
|
||||
if((*this)[i]<other[i]){
|
||||
return true;
|
||||
}else if((*this)[i]>other[i]){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool operator==(const Version&other)const{
|
||||
for(int i=0;i<max(v.size(),other.v.size());i++){
|
||||
if((*this)[i]!=other[i]){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
inline int compareVersion(string version1, string version2) {
|
||||
Version v1=version1;
|
||||
Version v2=version2;
|
||||
if(v1==v2)return 0;
|
||||
return v1<v2?-1:1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(){
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user