P7075 儒略日(2020CSP-S T1)
考试的时候就一个地方写挂了啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,要不然就完成了场切大模拟的壮举
思路
有什么思路啊,就模拟啊。。。首先发现1582年之前是白给,我一开始决定整个题都使用取模操作。但是我发现公元前4713年1月1日是第0天,也就是这一天不算在儒略日内,但是公元1年1月1日是算的,这就导致它们之间的代码有很多细节都不一样,我也就是这里写挂了。其实公元前取模操作比较好写,好吧其实差不多的,但我考场上就是取模取挂了,本来应该是1111年12月31号,我取模一个细节炸了,输出了1115年12月31号。痛失60pts。但是无所谓,毕竟这次考试并不重要。所以我改成公元后一年一年地跑,就算全是极限数据,也才是1e8(我相信i7的实力),是可以跑的,况且出题人不可能构造这样的数据,那1e5组不可能都是1582年之前的,显然1582年之后更恶心。这样暴力跑完之后,1582年之后必须取模了,不然复杂度炸裂。注意到闰年是400年一个周期,也就是说我们可以算出400年一共多少天,然后对它取模,就可以将年份确定在400年的一个区间里,在这个区间内再一年一年跑,时间复杂度最差是\(O(400Q)\),对i7来说小菜一碟,而且不可能这么精准地卡到我最差时间复杂度。当然,为了便于实现,我特判了1582年到1582年之间的部分,从1583年1月1日开始算,会更加方便。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<ctime>
#include<map>
using namespace std;
typedef long long ll;
inline ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
ll Q,r,ri,yue,nian;
ll run[15]={0,31,29,31,30,31,30,31,31,30,31,30,31};
ll ping[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
Q=read();
while(Q--){
r=read();
if(r<=1721423){//公元前
ll sum1=r/1461,sum2=r%1461+1;
nian=4713-sum1*4;//取模操作,细节手玩即可
for(ll i=nian;i;i--){
if(nian%4==1){
if(sum2<=366){
break;
}
else{
sum2-=366;
nian--;
}
}
else{
if(sum2<=365){
break;
}
else{
sum2-=365;
nian--;
}
}
}
if(nian%4==1){
for(ll i=1;i<=12;i++){
if(sum2<=run[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=run[i];
}
}
}
else{
for(ll i=1;i<=12;i++){
if(sum2<=ping[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=ping[i];
}
}
}//确定区间后一年一年跑
printf("%lld %lld %lld BC\n",ri,yue,nian);
continue;
}
else{
r-=1721423;//减去公元前的天数
if(r<=577737){//1582年之前
nian=1;
ll sum2=r;
for(int i=nian;i;i++){//直接暴力枚举
if(i%4==0){
if(sum2<=366){
break;
}
else{
sum2-=366;
nian++;
}
}
else{
if(sum2<=365){
break;
}
else{
sum2-=365;
nian++;
}
}
}
if(nian%4==0){
for(int i=1;i<=12;i++){
if(sum2<=run[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=run[i];
}
}
}
else{
for(int i=1;i<=12;i++){
if(sum2<=ping[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=ping[i];
}
}
}
printf("%lld %lld %lld\n",ri,yue,nian);
}
else{//1582年之后
r-=577737;
nian=1582;
if(r<=78){
if(r<=78&&r>47){
ri=r-47;
yue=12;
}
if(r<=47&&r>17){
ri=r-17;
yue=11;
}
if(r<=17&&r>0){
ri=r+14;
yue=10;
}
printf("%lld %lld %lld\n",ri,yue,nian);
continue;
}//特判到1583年
nian=1583;
r-=78;
ll sum1=r/146097,sum2=r%146097;
nian+=sum1*400;
if(sum2==0){
nian-=400;
sum2=146097;
}
for(ll i=nian;i;i++){
if(nian%4==0){
if(nian%100!=0||nian%400==0){
if(sum2<=366){
break;
}
else{
sum2-=366;
nian++;
}
}
else{
if(sum2<=365){
break;
}
else{
sum2-=365;
nian++;
}
}
}
else{
if(sum2<=365){
break;
}
else{
sum2-=365;
nian++;
}
}
}
if(nian%4==0){
if((nian%100!=0)||(nian%400==0)){
for(ll i=1;i<=12;i++){
if(sum2<=run[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=run[i];
}
}
}
else{
for(ll i=1;i<=12;i++){
if(sum2<=ping[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=ping[i];
}
}
}
}
else{
for(ll i=1;i<=12;i++){
if(sum2<=ping[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=ping[i];
}
}
}
printf("%lld %lld %lld\n",ri,yue,nian);
}
}
}
return 0;
}
\(upd:取模板de出bug了,不过我NOIp也炸了。。。\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<ctime>
#include<map>
using namespace std;
typedef long long ll;
inline ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
ll Q,r,ri,yue,nian;
ll run[15]={0,31,29,31,30,31,30,31,31,30,31,30,31};
ll ping[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
// freopen("P7075_6.in","r",stdin);
// freopen("julian3.out","w",stdout);
Q=read();
while(Q--){
r=read();
if(r<=1721423){
ll sum1=r/1461,sum2=r%1461+1;
nian=4713-sum1*4;
for(ll i=nian;i;i--){
if(nian%4==1){
if(sum2<=366){
break;
}
else{
sum2-=366;
nian--;
}
}
else{
if(sum2<=365){
break;
}
else{
sum2-=365;
nian--;
}
}
}
if(nian%4==1){
for(ll i=1;i<=12;i++){
if(sum2<=run[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=run[i];
}
}
}
else{
for(ll i=1;i<=12;i++){
if(sum2<=ping[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=ping[i];
}
}
}
printf("%lld %lld %lld BC\n",ri,yue,nian);
continue;
}
else{
r-=1721423;
if(r<=577737){
ll sum1=r/1461,sum2=r%1461;
nian=sum1*4+1;
if(sum2==0){
nian-=4;
sum2=1461;
}
for(int i=nian;i;i++){
if(i%4==0){
if(sum2<=366){
break;
}
else{
sum2-=366;
nian++;
}
}
else{
if(sum2<=365){
break;
}
else{
sum2-=365;
nian++;
}
}
}
if(nian%4==0){
for(int i=1;i<=12;i++){
if(sum2<=run[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=run[i];
}
}
}
else{
for(int i=1;i<=12;i++){
if(sum2<=ping[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=ping[i];
}
}
}
printf("%lld %lld %lld\n",ri,yue,nian);
}
else{
r-=577737;
nian=1582;
if(r<=78){
if(r<=17){
ri=r+14;
yue=10;
}
if(r>17&&r<=47){
ri=r-17;
yue=11;
}
if(r>47&&r<=78){
ri=r-47;
yue=12;
}
printf("%lld %lld %lld\n",ri,yue,nian);
continue;
}
nian=1583;
r-=78;
ll sum1=r/146097,sum2=r%146097;
nian+=sum1*400;
if(sum2==0){
nian-=400;
sum2=146097;
}
for(ll i=nian;i;i++){
if(nian%4==0){
if(nian%100!=0||nian%400==0){
if(sum2<=366){
break;
}
else{
sum2-=366;
nian++;
}
}
else{
if(sum2<=365){
break;
}
else{
sum2-=365;
nian++;
}
}
}
else{
if(sum2<=365){
break;
}
else{
sum2-=365;
nian++;
}
}
}
if(nian%4==0){
if((nian%100!=0)||(nian%400==0)){
for(ll i=1;i<=12;i++){
if(sum2<=run[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=run[i];
}
}
}
else{
for(ll i=1;i<=12;i++){
if(sum2<=ping[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=ping[i];
}
}
}
}
else{
for(ll i=1;i<=12;i++){
if(sum2<=ping[i]){
yue=i;
ri=sum2;
break;
}
else{
sum2-=ping[i];
}
}
}
printf("%lld %lld %lld\n",ri,yue,nian);
}
}
}
return 0;
}