今天开始打算做一下历年的noip和csp的真题,感受一下到底考了哪些内容。
先从csp-s 2020开始吧,首先是这道T1,昨天调了一天。。。
csp的好像牛客网没有找到,我在洛谷做的。
题目链接:
https://www.luogu.com.cn/problem/P7075
思路:
看题目就知道模拟肯定可以。
我在这里分了几种情况:
① 公元前,从-4713到-1年。一共4713年,其中根据题目意思,-1,-5,-9...-4713是闰年。
那么我们一共有1178个闰年,3535个平年,一共有t1=1721423天。
所以第一段就是当输入的天数T<=1721423,我们可以直接统一输出到公元前的情况。这里显然是4年一周期,那么我们可以得到一个周期为366+365*3=1461天,那我们先4年4年的算,然后直接模拟月和日的情况。
②公元后,我在这里处理到从1年1月1日到1582年10月4日,这里先计算1-1581年的天数,395个闰年+1186个平年,再加上1582年的277天,一共有t2=577460天。
所以第二段就是当输入的天数T <= t1+t2 = 2299160天时候,我们输出公元1年到1582年的情况,这里也是4年一周期,先对T减去1721424以后,方法同第一种情况。
③从1582年10月15日以后就是格里高历了,那么在这里我先处理到了1582-10-15到1599-12-31的情况,这里一共是6287天,那么当T<=2305812时,这一部分我们直接模拟。
④最后模拟1600-1-1以后的情况,这里我们要注意闰年的判断方法改变了,不能再是4年一周期了。不过我们可以把周期扩大到400年,每400年中有97个闰年和303个平年,那么一共是146097天,每400年一个周期。
所以我们先计算出有多少个400年的周期,然后再模拟就好了。
说起来挺容易,其实中间模拟的时候有一些地方细节挺多。
中间有一个solve没有开longlong,T了好多发。
附上具丑的代码:
#include<bits/stdc++.h> using namespace std; int y[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int year,month,day; inline long long read() { long long x=0,y=1;char c=getchar();//y代表正负(1.-1),最后乘上x就可以了。 while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}//如果c是负号就把y赋为-1 while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*y;//乘起来输出 } void solve(long long d){ long long t=d/1461; //4年一周期 d-=t*1461; year=4713-t*4; month=1;day=1; int flag=0; while(d){ for(int i=1;i<=12;i++){ int tmp=y[i]; if(i==2&&(year-1)%4==0)tmp++; if(d>tmp)d-=tmp; else { month=i; day=d+1; if(day>tmp){ month++,day-=tmp; if(month>12)month=1,year--; } d=0; return; } } year--; } } void solve2(long long d){ long long t=d/1461; d-=t*1461; year=t*4+1; month=1; day=1; int flag=0; while(d){ int tmp=365; if(year%4==0)tmp++; if(d>tmp){ year++; d-=tmp; continue; } for(int i=1;i<=12;i++){ int tmp=y[i]; if(i==2&&year%4==0)tmp++; if(d>tmp)d-=tmp; else { month=i; day=d+1; if(day>tmp){ month++,day-=tmp; if(month>12)month=1,year++; } d=0; return ; } } year++; } } void solve3(long long d){ year=1582; month=10; day=15; if(d<=16){ day+=d; return; } d-=17; int flag=0; while(d){ for(int i=(flag==0)?11:1;i<=12;i++){ flag=1; int tmp=y[i]; if(i==2&&year%4==0)tmp++; if(d>tmp)d-=tmp; else { month=i; day=d+1; if(day>tmp){ month++,day-=tmp; if(month>12)month=1,year++; } d=0; return ; } } year++; } } bool judge(int x){ if(x%400==0)return true; else if(x%4==0&&x%100!=0)return true; return false; } void solve4(long long d){ long long t=d/146097; year=1600+t*400; month=1;day=1; d-=t*146097; while(d){ int tmp=365; if(judge(year))tmp++; if(d>tmp){ year++; d-=tmp; continue; } for(int i=1;i<=12;i++){ int tmp=y[i]; if(i==2&&judge(year))tmp++; if(d>tmp)d-=tmp; else { month=i; day=d+1; if(day>tmp){ month++,day-=tmp; if(month>12)month=1,year++; } d=0; return ; } } year++; } } int main() { // freopen("f2.in","r",stdin); // freopen("f.out","w",stdout); int Q; cin>>Q; long long d; while(Q--){ d=read(); if(d<=1721423){ //bc solve(d); printf("%d %d %d BC\n",day,month,year); } else if(d<=2299160){ // before 1582-10-4 d-=1721424; solve2(d); printf("%d %d %d\n",day,month,year); } else if(d<=2305447){ //1582-10-15 到1599-12-31 d-=2299161; solve3(d); printf("%d %d %d\n",day,month,year); } else{ //1600-1-1开始400年一周期 d-=2305448; solve4(d); printf("%d %d %d\n",day,month,year); } } return 0; }