专栏文章
题解:P7075 [CSP-S2020] 儒略日
P7075题解参与者 5已保存评论 4
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @miqlpbza
- 此快照首次捕获于
- 2025/12/04 06:51 3 个月前
- 此快照最后确认于
- 2025/12/04 06:51 3 个月前
这篇题解本来有很多前言,但是说多了都是泪,还是不说了。
题意
给定 ,请你求从公元前 4713 年 1 月 1 日往后数 天的日期。
简明的题意,屎山的代码。
思路
发现公元 1582 年 10 月 4 日之后改了历法,那么这里就是一个转折点。为了防止出错,我选择将此之前和此之后分开处理,写成
solve1() 和 solve2()。-
儒略历处理每 年有 天。我的做法的流程如下:
- 设 为经过了多少个整 年,即取 ,然后使天数 减去 。
- 取年份 。
- 因为公元零年并不存在,所以若 ,使 自增 。
- 因为公元前 4713 年 1 月 1 日被记作第 天,我们又是把公元前 4713 年 1 月 1 日当做第 天数的,所以要把 加上 。注意这里不可以一开始就这样做,否则会 分。
- 处理不足 年的整年。这一块可以枚举。从已经得到的 开始,只要 ,每次判断 是否是闰年。若是, 每次减去 ,否则每次减去 。每次 增加 。
- 处理月。设 表示 月有 天。先判断现在得到的年份 是否为闰年,若是把 设为 ,否则设为 。从一月开始,设月份 ,只要 , 每次增加 , 减去 。
- 这时我们已经处理好了年和月,剩下的 就是日期。但是还有很多细节等待我们处理。让我们一一处理这些细节。
由于前面年是一个一个加的,所以有可能加到 年,把它变成 年就好了。
因为月份是从 开始数的,所以有可能会数到 月。需要把年份加 ,把月份变为 。
输出时,要输出 ,若 ,不要忘了输出BC。
好的那么
solve1() 就大功告成了。solve2() 只需要在 solve1() 的基础上改一些地方。- 每 年有 天,所以取 。
- 我们是从公元 1582 年 10 月 15 日开始数的,所以要把 减去 ,这是从公元前 4713 年 1 月 1 日到公元 1582 年 10 月 15 日的天数;把 的初始值赋成 ,再把 加上 ,这是从 1 月 1 日到 10 月 15 日的天数。
- 免去了判断公元前和零年的判断,因为最少到 1582 年。
考虑主函数里怎么写。考虑到换历法删除的 天,若该日期在公元 1582 年 10 月 15 日(含)以后,直接把 加上 即可。
按儒略历手算可以算出公元 1582 年 10 月 4 日的儒略日是 。所以判断若 ,按儒略日用
solve1() 处理,否则将 加上 ,用 solve2() 处理。最后也是最重要的判断闰年。仔细读题可以发现,1582 年之前用的儒略历,只要年份是 的倍数就闰,否则就是我们熟悉的闰年法。对于公元前的年份 ,应把它看做 年。
到这就写完了,可是这些调了我 3 天。我的码风不怎么样,写了 70 行。
AC Code
CPP#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,x;
int month[15]= {29,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int x) {
if(x<=1582) {//如果是儒略历判断闰年就是4年一闰
if(x<=0) x=-x-1;
return x%4==0;
}
if(x%400==0||(x%4==0&&x%100!=0)) return 1;//格里高利历判断闰年
return 0;
}
void solve1(int x) {
int N=x/146100;
int y=-4713+N*400;
if(y>1) y++;
x-=N*146100;//处理整400年
x++;
for(; x>366; y++) {//处理整年
int f=0;
if(y==0) y++;
f=check(y);
if(f) x-=366;
else x-=365;
}
int yue=1;
int f=0;
f=check(y);
if(f) month[2]=29;//如果是闰年,把month[2]设成29
for(; yue<=12&&x>month[yue]; yue++) x-=month[yue];//处理月
if(y==0) y=1;
if(yue==13) yue=1,y++;//处理细节
cout<<x<<' '<<yue<<' '<<abs(y);
if(y<0) cout<<" BC";
cout<<endl;
}
void solve2(int x) {
x-=2299171;
int y=1582,yue=1;
x+=287;
int N=x/146097;
y+=N*400;
x-=N*146097;
x++;
for(; x>366; y++) {
int f=0;
f=check(y);
if(f) x-=366;
else x-=365;
}
int f=0;
f=check(y);
if(f) month[2]=29;
for(; yue<=12&&x>month[yue]; yue++) x-=month[yue];
if(yue==13) yue=1,y++;
cout<<x<<' '<<yue<<' '<<y;
cout<<endl;
}
signed main() {
cin>>T;
while(T--) {
cin>>x;
month[2]=28;
if(x>=2299161) x+=10;
if(x<=2299160) solve1(x);//判断用solve1还是solve2
else solve2(x);
}
return 0;
}
相关推荐
评论
共 4 条评论,欢迎与作者交流。
正在加载评论...