今天开始打算做一下历年的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;
}
京公网安备 11010502036488号