儒略日 题解
2022-11-11 22:44:17
发布于:天津
158阅读
0回复
0点赞
从题目给出的条件,我们不难发现将一个年份转化为儒略??将一个儒略日转化为年份要相对简单,于是我们可以写一个转化的函数,再使用二分答案找到年份
年份分公元前和公元,公元前用负数表示,公元用正数
注意:公元0年不存在,18xx年是19世纪所以我们往前加一年,从公元前4712年开始计算,如果答案是公元前就再减回来。而这里又要注意,公元前4712年恰好也是闰年,还要再加一天
#include <iostream>
#define ull unsigned long long
using namespace std;
ull year_to_day(int year){
int start = -4712;//公元元年不存在
if (year < start) return 0;
ull res = (year - start + 1) * 365;
if (year < 1582) {
res += (year - start) / 4 + 1;//儒略历
} else {
res -= 10;//消失的10天
res += (1581 - start)/4 + 1; //1582年以前用儒略历
res += (year-1580)/4 - (year-1500)/100 +(year-1200)/400; // 1582年后用格里高利历,容斥原理求闰年数
}
return res;
}
二分答案:
int l=-4712,r=1e9+5,mid;
while(l<r){
mid=(l+r)>>1;
if(year_to_day(mid)>=d)r=mid;
else l=mid+1;
}
到现在,我们已经确定了年份
如何求剩下的天数呢?我们可以用总儒略日数减去截止去年的总儒略日,剩下的就是今年还剩多少天
用总天数依次减每个月的天数,直到不够减了,月份和日期就都出来了
记得,闰年2月有29天,1582年10月只有21天
代码
#include <iostream>
#define int long long
#define ull unsigned long long
using namespace std;
int T;
ull d,m;
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//每月天数列表
ull year_to_day(int year){
int start = -4712;//公元元年不存在
if (year < start) return 0;
ull res = (year - start + 1) * 365;
if (year < 1582) {
res += (year - start) / 4 + 1;//儒略历
} else {
res -= 10;
res += (1581 - start)/4 + 1; //1582年以前用儒略历
res += (year-1580)/4 - (year-1500)/100 +(year-1200)/400; // 1582年后用格里高利历,容斥原理求闰年数
}
return res;
}
bool pd(int x){//判断是否是闰年
if (x>=1582)return(x%4==0&&x%100!=0)||(x%400==0);
else return x % 4 == 0;
}
signed main(){
cin >> T;
while(T--){
cin >> d;
d++;
int l=-4712,r=1e9+5,mid;
while(l<r){//二分答案
mid=(l+r)>>1;
if(year_to_day(mid)>=d)r=mid;
else l=mid+1;
}
d-=year_to_day(l-1);//减去去年
a[2]=28+pd(l);
a[10] = l==1582 ? 21 : 31;//特判
for(int i=1;i<=12;i++){//确定月份和日期
if(d>a[i])d-=a[i];
else{
m=i;
break;
}
}
if(l==1582&&m==10&&d>=5)d+=10;//1582年10月没有5-14日,10.4明天就是10.15
if(l>0)cout << d << " " << m << " " << l << endl;
else cout << d << " " << m << " " << 1-l << " BC" << endl;//加的一年要减回去
}
return 0;
}
记得开long long
全部评论 1
张五书记~
2023-09-20 来自 浙江
22024-10-13 来自 上海
0
有帮助,赞一个