题解 P7075 【儒略日(洛谷民间数据)】
PrincessQi · · 题解
0.题外话:
CSP-S T1 放这个真的好吗。。。T2都比这个简单
1. 10 分做法
由于第一个点
等等,好像没那么简单?
有的同学发现了一点:一月一日是第
其实公元前4713年是一个闰年,因为
所以只要枚举判断月份的前缀和是否超过了
month[2]++;
int qwq=0,mth;
for(int i=1;i<=12;i++){
qwq+=month[i];
if(qwq>=k){
mth=i;
k-=(qwq-month[i]);
printf("%lld %lld 4713 BC\n",k,mth);
break;
}
}
month[2]--;
2. 40 分做法
首先,公元1582年10月4日是第
那如何处理儒略历呢?
注意到,儒略历
然后再向上面一样判断月、日就好了。
void count_date(int year,int k,int r){
if(r==1)month[2]++;
int qwq=0,mth;
for(int i=1;i<=12;i++){
qwq+=month[i];
if(qwq>=k){
mth=i;
k-=(qwq-month[i]);
if(year-4713<0)printf("%lld %lld %lld BC\n",k,mth,4713-year);
else printf("%lld %lld %lld\n",k,mth,year-4712);
break;
}
}
if(r==1)month[2]--;
}
scanf("%lld",&n);
int k=n%(365*4+1),year=n/(365*4+1)*4,r=1;
if(k>=366)k-=365,year++,r=0;
if(k>=366)k-=365,year++;
if(k>=366)k-=365,year++;
if(r==1)k++;
count_date(year,k,r);
3. 100 分做法
没错,就是
首先,对于格里高利历,有个很没良心的地方:当年份是
所以,变成了
其实和
具体来说,就是把那几个if语句写个循环,道理是一样的。
注意,循环里还是要判断闰年。
还有,由于以公元1600年1月1日为原点写起来会比较舒服(周期起点),所以可以为了减少代码量,特判一下公元1582年和公元1600年之间的那几年。
下面是完整的代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int q,n,rsum,month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
void count_date(int year,int k,int r){
if(r==1)month[2]++;
int qwq=0,mth;
for(int i=1;i<=12;i++){
qwq+=month[i];
if(qwq>=k){
mth=i;
k-=(qwq-month[i]);
if(year-4713<0)printf("%lld %lld %lld BC\n",k,mth,4713-year);
else printf("%lld %lld %lld\n",k,mth,year-4712);
break;
}
}
if(r==1)month[2]--;
}//儒略历时代的count_date
void count_date2(int year,int k,int r){
if(r==1)month[2]++;
int qwq=0,mth,f=0;
for(int i=1;i<=12;i++){
qwq+=month[i];
if(qwq>=k){
mth=i;
k-=(qwq-month[i]);
printf("%lld %lld %lld\n",k,mth,year+1600);
f=1;
break;
}
}
if(f==0)printf("1 1 %lld\n",year+1601);
if(r==1)month[2]--;
}//格里高利历时代的count_date
signed main(){
//freopen("julian.in","r",stdin);
//freopen("julian.out","w",stdout);
for(int i=1;i<=400;i++)
if((i%4==0&&i%100!=0)||i%400==0)rsum++;
scanf("%lld",&q);
while(q--){
scanf("%lld",&n);
if(n<=2299160){
int k=n%(365*4+1),year=n/(365*4+1)*4,r=1;
if(k>=366)k-=365,year++,r=0;
if(k>=366)k-=365,year++;
if(k>=366)k-=365,year++;
if(r==1)k++;
count_date(year,k,r);
}//儒略历时代
else {
n+=10;//完美跳过不存在的那几天
if(n<=2305457){
int k=n%(365*4+1),year=n/(365*4+1)*4,r=1;
if(k>=366)k-=365,year++,r=0;
if(k>=366)k-=365,year++;
if(k>=366)k-=365,year++;
if(r==1)k++;
count_date(year,k,r);
}//特判的那几年
else{
n-=2305458;
int k=n%(365*400+rsum),year=n/(365*400+rsum)*400,r=1;
if(k>=366)k-=365,year++,r=0;
for(int i=2;i<=399;i++){
if(i%4==0&&i%100!=0){
if(k>=367)k-=366,year++,r=1;
else break;
}
else{
if(k>=366)k-=365,year++,r=0;
else break;
}
}
if(r==1)k++;
count_date2(year,k,r);
}//格里高利历时代
}
}
return 0;
}
时间复杂度:这看起来暴力的做法实际上是 不过常数比较大。