今儿终于做掉困扰多年的题目了,其实想好细节也不难。
容易发现儒略历和格里高利历的润年判断方式不一样,并且中间有消失的十天,计算起来相当不方便。所以我们可以首先计算出 \(-4713.1.1\) ~ \(1582.10.4\) 会经过多少天,可以通过一天一天暴力跳的方法计算出需要 \(2299160\),那么对于小于等于该数字的情况,直接按照儒略历的计算方式从 \(-4713.1.1\) 计算即可,否则先将天数减去 \(2299161\) 然后按照格里高利历从 \(1582.10.15\) 开始计算。
对于儒略历,可以发现,4年一闰,所以先除掉4年的天数,然后一月一月的跳,最后一天一天地跳。
对于格里高利历,400年总共有97闰,所以先400年跳,然后一年一年跳,再一月一月跳,最后一天一天跳。
对于代码实现,可以使用查表的方式简化计算。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL read() {
LL sum=0,flag=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') flag=-1; c=getchar();}
while(c>='0'&&c<='9') {sum=sum*10+c-'0'; c=getchar();}
return sum*flag;
}
#define int LL
int T;
int year[2]={365,366};
int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
inline int chkru(int x) {
if(x<0) x++;
if(x%4==0) return 1;
else return 0;
}
inline int chkge(int x) {
if((x%4==0&&x%100!=0)||x%400==0) return 1;
else return 0;
}
inline void calc_ru(int n) {
int a=-4713,b=1,c=1;
a=a+4*int(n/1461); n%=1461;
if(a>=0) a++;
while(n>=month[b][chkru(a)]) {
n-=month[b][chkru(a)];
b++;
if(b==13) {
b=1;
if(a==-1) a=1;
else a++;
}
}
while(n--) {
c++;
if(c==month[b][chkru(a)]+1) {
c=1; b++;
if(b==13) {
b=1;
if(a==-1) a=1;
else a++;
}
}
}
if(a<0) cout<<c<<" "<<b<<" "<<-a<<" BC"<<endl;
else cout<<c<<" "<<b<<" "<<a<<endl;
}
inline void calc_ge(int n) {
int a=1582,b=10,c=15;
a=a+400*int(n/146097); n%=146097;
while(n>=year[chkge(a+1)]) {
n-=year[chkge(a+1)];
a++;
}
while(n>=month[b][chkge(a)]) {
n-=month[b][chkge(a)];
b++; if(b==13) {b=1; a++;}
}
while(n--) {
c++;
if(c==month[b][chkge(a)]+1) {
c=1; b++;
if(b==13) {b=1; a++;}
}
}
cout<<c<<" "<<b<<" "<<a<<endl;
}
signed main() {
cin>>T;
while(T--) {
int n; cin>>n;
if(n<=2299160) calc_ru(n);
else calc_ge(n-2299161);
}
}
标签:13,++,题解,month,儒略,while,计算,chkge,CSP
From: https://www.cnblogs.com/zhangyuzhe/p/17798941.html