专栏文章

题解:P7075 [CSP-S2020] 儒略日

P7075题解参与者 5已保存评论 7

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
7 条
当前快照
1 份
快照标识符
@miqlnwzc
此快照首次捕获于
2025/12/04 06:50
3 个月前
此快照最后确认于
2025/12/04 06:50
3 个月前
查看原文
update:发现了一处错别字

题意

给出一个儒略日日期,需要我们将它转化成格里高利历(公历)日期。
推荐一个好用的小工具,可以帮助检验代码问题:儒略日数和日干支计算器,注意表格中的日期如果是公元前的话要减一,建议看中部的蓝字显示的日期。

思路

其实就是暴力模拟,但是需要注意不少要点,也可以说是坑点。
  • 闰年的判断方式不同,在 15821582 及以前判断闰年只需要判断是否为 44 的倍数即可,但在 15831583 及以后,判断闰年的方法便变为需要满足年份是 400400 的倍数或者年份是 44 的倍数且不是 100100 的倍数。
  • 当年份是公元前的年份时,因为没有公元零年,必须将年份先加一,再判断是否为 44 的倍数。
    这样看来,这个题还是比较水的,但是当你打完下面给出的暴力后,会看到只有 5050 分,并且还是超时了。
    暴力 6060 分代码:
CPP
#include <bits/stdc++.h>
#define  int long long
#define  rint register int
#define  ll long long
#define  INF 0x3f3f3f3f
#define  LINF 0x3f3f3f3f3f3f3f3f
#define  bug puts("!!!====!!!=");
using namespace std;
int t,n,day,year,month,aly;
int date[2][13]={0,31,28,31,30,31,30,31,31,30,31,30,31,0,31,29,31,30,31,30,31,31,30,31,30,31};;
bool BC,flag,ru;
bool run(int x){
	if(BC){
		x++;
		if(x%4==0){
			return 1;
		}
		return 0;
	}
	if((x%400==0)||(x%4==0&&x%100!=0)||(x%4==0&&ru)){
		return 1;
	}
	return 0;
}
signed main(){
	BC=1;
	BC=1;
	cin>>t; 
	while(t--){
		cin>>n;
		BC=1;
		ru=1;
		year=-4713;
		month=1;
		day=1;
		while(1){
			if(year==1582){
				ru=0;
			}
			if(!run(year)){
				if(n>=355){
					n-=355;
					if(year!=1582){
						n-=10;
						if(n<0){
							n+=365;
							break;
						}
					}
					year++;
					if(year==0){
						year++;
						BC=0;
					}
				}
				else{
					break;
				}
			}
			else{
				if(n>=356){
					n-=356;
					if(year!=1582){
						n-=10;
						if(n<0){
							n+=366;
							break;
						}
					}
					year++;
					if(year==0){
						year++;
						BC=0;
					}
				}
				else{
					break;
				}
			}
		}
		flag=run(year);
		while(n--){
			day++;
			if(day==date[flag][month]+1){
				day=1;
				month++;
			}
			if(year==1582&&month==10&&day==5){
				day=15;
			}
		}
		cout<<day<<' '<<month<<' '<<abs(year);
		if(BC){
			cout<<" BC";
		}
		cout<<'\n';
	}
    return 0;
}
那么此刻,很多人既不知道如何优化,又不想重写代码,诶,那么此时,我们会发现一个规律:在 18521852 年(既开始使用格里高利历)后,每 400400 年为一个周期,那么我们选择 800008000080008000800800 来进行循环,只需要在循环时把减去每年的天数变成减去 800008000080008000800800 年的天数即可。
那么这样我们便得到了一段优化代码:
CPP

		while(n-29219400>0){
			n-=29219400;
		   year+=80000;
		}
		while(n-2921940>0){
			n-=2921940;
			year+=8000;
		}
		while(n-292194>0){
			n-=292194;
			year+=800;
		}

完整代码

其实一开始我是写火车头的,但是害怕审核直接因为码风不好直接给我毙掉,含泪删代码。
CPP
#include <bits/stdc++.h>
#define  int long long
#define  rint register int
#define  ll long long
#define  INF 0x3f3f3f3f
#define  LINF 0x3f3f3f3f3f3f3f3f
#define  bug puts("!!!====!!!=");
using namespace std;
int t,n,day,year,month,aly;
int date[2][13]={0,31,28,31,30,31,30,31,31,30,31,30,31,0,31,29,31,30,31,30,31,31,30,31,30,31};;
bool BC,flag,ru;
bool run(int x){
	if(BC){
		x++;
		if(x%4==0){
			return 1;
		}
		return 0;
	}
	if((x%400==0)||(x%4==0&&x%100!=0)||(x%4==0&&ru)){
		return 1;
	}
	return 0;
}
signed main(){
	BC=1;
	BC=1;
	cin>>t; 
	while(t--){
		cin>>n;
		BC=1;
		ru=1;
		year=-4713;
		month=1;
		day=1;
		if(n>=1721424){
			n-=1721424;
			BC=0;
			year=1;
		}
		while(1){
			if(year==1582){
				ru=0;
			}
			if(!run(year)){
				if(n>=355){
					n-=355;
					if(year!=1582){
						n-=10;
						if(n<0){
							n+=365;
							break;
						}
					}
					year++;
					if(year==0){
						year++;
						BC=0;
					}
				}
				else{
					break;
				}
			}
			else{
				if(n>=356){
					n-=356;
					if(year!=1582){
						n-=10;
						if(n<0){
							n+=366;
							break;
						}
					}
					year++;
					if(year==0){
						year++;
						BC=0;
					}
				}
				else{
					break;
				}
			}
			if(year==1583){
				break;
			}
		}
		while(n-29219400>0){
			n-=29219400;
		   year+=80000;
		}
		while(n-2921940>0){
			n-=2921940;
			year+=8000;
		}
		while(n-292194>0){
			n-=292194;
			year+=800;
		}
		while(n-365>0){
			n-=365;
			if((year%4==0&&year%100!=0)||year%400==0){
				n--;
			}
			year++;
		}
		flag=run(year);
		while(n--){
			day++;
			if(day==date[flag][month]+1){
				day=1;
				month++;
				if(month==13){
					month=1;
					year++;
					flag=run(year);
				}
			}
			if(year==1582&&month==10&&day==5){
				day=15;
			}
		}
		cout<<day<<' '<<month<<' '<<abs(year);
		if(BC){
			cout<<" BC";
		}
		cout<<'\n';
	}
    return 0;
}

评论

7 条评论,欢迎与作者交流。

正在加载评论...