1 条题解

  • -1
    @ 2025-10-11 14:10:33

    按照题意模拟即可。

    由于年代不同,闰年计算方式不同,而且中间还有删除的部分。所以我们分成四个部分处理:

    1. 公元前 4713 年 1 月 1 日至公元前 1 年 12 月 31 日。

    2. 公元 1 年 1 月 1 日至公元 1582 年 10 月 4 日。

    3. 公元 1582 年 10 月 15 日至公元 1582 年 12 月 31 日。

    4. 公元 1583 年 1 月 1 日至时间轴无穷远处。

    我们预处理出平年/闰年的第 ii 天的日期。然后对于每一部分,我们使用二分求出儒略日所在年份,然后会剩下一些天数,查表就行了。

    代码细节较多,但理清思路后比较好实现。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    inline int read() {
    	int x=0,y=1;
    	char e=getchar();
    	while(e<'0'||e>'9') {
    		if(e=='-')y=-1;
    		e=getchar();
    	}
    	while(e>='0'&&e<='9') {
    		x=(x<<1)+(x<<3)+(e-'0');
    		e=getchar();
    	}
    	return x*y;
    }
    
    inline bool f29(int y,int op) {
    	if(op==0) {
    		//op=0 is julian calendar
    		if((abs(y)-1)%4==0)return 1;
    		return 0;
    	} else if(op==1) {
    		//op=1 is gregorian calendar
    		if(y%400==0||(y%100!=0&&y%4==0))return 1;
    		return 0;
    	} else {
    		if(y%4==0)return 1;
    		return 0;
    	}
    }
    pair<int,int> res[2][400];
    //0 is ping year; 1 is run year
    int pmonth_cnt[]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
    int rmonth_cnt[]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
    signed main() {
    //	freopen("julian.in","r",stdin);
    //	freopen("julian.out","w",stdout);
    	for(int i=1,tot=0; i<=12; ++i) {
    		for(int j=1; j<=pmonth_cnt[i]; ++j) {
    			res[0][++tot]= {i,j};
    		}
    	}
    	for(int i=1,tot=0; i<=12; ++i) {
    		for(int j=1; j<=rmonth_cnt[i]; ++j) {
    			res[1][++tot]= {i,j};
    		}
    	}
    	int T=read();
    	while(T--) {
    		int n=read();
    		if(n<1721424) {
    			// BCE 4713*365+1179
    			int l=1,r=4713,mid,ans=r;
    			while(l<=r) {
    				mid=(l+r)>>1;
    				if((4713-mid)*365+(4713-mid+3)/4<=n) ans=mid,r=mid-1;
    				else l=mid+1;
    			}
    			n-=(4713-ans)*365+(4713-ans+3)/4-1;
    			cout<<res[f29(ans,0)][n].second<<" "<<res[f29(ans,0)][n].first<<" "<<ans<<" BC\n";
    		} else if(n<2299161) {
    			// [1.1.1~1582.10.4] 1721424+1581*365+395+277
    			n-=1721424;
    			int l=1,r=1582,mid,ans=1;
    			while(l<=r) {
    				mid=(l+r)>>1;
    				if((mid-1)*365+(mid-1)/4<=n)ans=mid,l=mid+1;
    				else r=mid-1;
    			}
    			n-=(ans-1)*365+(ans-1)/4-1;
    			cout<<res[f29(ans,2)][n].second<<" "<<res[f29(ans,2)][n].first<<" "<<ans<<"\n";
    		} else if(n<2299239) {
    			//1582.10.15~1582.12.31
    			n-=2299161;
    			int i=10,j=15;
    			while(n--) {
    				if(j==pmonth_cnt[i])++i,j=1;
    				else ++j;
    			}
    			cout<<j<<" "<<i<<" "<<"1582\n";
    		} else {
    			//1583.1.1~inf
    			n-=2299239;
    			int l=1583,r=1000000000,mid,ans=r;
    			while(l<=r) {
    				mid=(l+r)>>1;
    				if((mid-1583)*365+(mid-1583+2)/4-(mid-1583+82)/100+(mid-1583+382)/400<=n)ans=mid,l=mid+1;
    				else r=mid-1;
    			}
    			n-=(ans-1583)*365+(ans-1583+2)/4-(ans-1583+82)/100+(ans-1583+382)/400-1;
    			cout<<res[f29(ans,1)][n].second<<" "<<res[f29(ans,1)][n].first<<" "<<ans<<"\n";
    		}
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    462
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    (无)
    递交数
    15
    已通过
    6
    上传者