zoukankan      html  css  js  c++  java
  • 【题解】[CSP-S 2020] 儒略日【大模拟】

    题目链接

    题目链接

    (题意略)

    题解

    巨大模拟即可。二分会好些很多。我的写法是:

    • 1582 年 10 月 15 日及之后的日子加上 10,毕竟消失的 10 天很毒瘤;
    • 关于公元 1 年 1 月 1 日与 1583 年分段处理;
    • 实行格里高利历之前先找到这是在哪个四年,然后找到这是在哪一年,然后是哪一月,哪一日;
    • 实行格里高利历之后依次找到这是在哪个四百年、哪个百年、哪个四年、哪个年、哪个月、哪一天。

    考场上处理错了公元前的闰年的最后一天和 1582 年 10 月 15 日。

    代码;

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll getint(){
    	ll ans=0,f=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-')f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		ans=ans*10+c-'0';
    		c=getchar();
    	}
    	return ans*f;
    }
    int mo[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    ll d0=0; // the Julian day of 1/1/1
    ll d1=0; // the Julian day of 1582/10/15
    ll d2=0; // the Julian day of 1583/1/1 if 1582/10/5~14 exists
    ll d3=0; // the Julian day of 1583/1/1
    		 // if 1582/10/5~14 exists and people used Gregorian from 1/1/1
    
    int m_(int i,int y){
    	if(y<0)++y;
    	if(i!=2)return mo[i];
    	if(y<=1582)return mo[i]+(y%4==0);
    	else return mo[i]+(y%4==0&&(y%100!=0||y%400==0));
    }
    int main(){
    	for(int i=4712;i>=0;--i)d0+=365+(i%4==0);
    	d1=d0;
    	d3=d0;
    	for(int i=1;i<=1581;i++)d1+=365+(i%4==0);
    	for(int i=1;i<=1582;i++)d3+=365+(i%4==0&&(i%100!=0||i%400==0));
    	// now d1 is the Julian day of 1582/1/1
    	d2=d1+365;
    	for(int i=1;i<=9;i++)d1+=mo[i];
    	d1+=4;
    /****************** Wrong Code ****************
        d1+=5;
     * ********************************************/
    	int n=getint();
    	while(n--){
    		ll x=getint();
    		if(x<d0){
    			int y=4713-x/(365*4+1)*4;x%=(365*4+1);
    			if(x>=366){y--,x-=366; // 4713 BC passed
    			if(x>=365)y--,x-=365; // 4714 BC passed
    			if(x>=365)y--,x-=365; // 4715 BC passed
    			//if(x>=365)assert(0);  // 4716 BC passed (This shouldn't happen)
                }
    /****************** Wrong Code ****************
    			if(x>=366)y--,x-=366; // 4713 BC passed
    			if(x>=365)y--,x-=365; // 4714 BC passed
    			if(x>=365)y--,x-=365; // 4715 BC passed
    			//if(x>=365)assert(0);  // 4716 BC passed (This shouldn't happen)
     * ********************************************/
    			int m=1;
    			while(x-m_(m,-y)>=0)x-=m_(m,-y),m++;
    			int d=x+1;
    			printf("%d %d %d BC
    ",d,m,y);
    			continue;
    		}
    		if(x>=d1)x+=10; // Don't care about the lost 10 days elsewhere
    		if(x>=d0&&x<d2){
    			x-=d0;
    			int y=x/(365*4+1)*4+1;x%=(365*4+1);
    			if(x>=365)y++,x-=365; // 1 passed
    			if(x>=365)y++,x-=365; // 2 passed
    			if(x>=365)y++,x-=365; // 3 passed
    			//if(x>=366)assert(0);  // 4 passed (This shouldn't happen)
    			int m=1;
    			while(x-m_(m,y)>=0)x-=m_(m,y),m++;
    			int d=x+1;
    			printf("%d %d %d
    ",d,m,y);
    			continue;
    		}
    		if(x>=d2){
    			x-=d0;
    			x+=d3-d2;
    			int y=x/(365*400+24*4+1)*400+1;x%=(365*400+24*4+1);
    			if(x>=365*100+24)y+=100,x-=365*100+24;
    			if(x>=365*100+24)y+=100,x-=365*100+24;
    			if(x>=365*100+24)y+=100,x-=365*100+24;
    			//if(x>=365*100+25)assert(0);
    			y+=x/(365*4+1)*4,x%=(365*4+1);
    			if(x>=365)y++,x-=365; // 1 passed
    			if(x>=365)y++,x-=365; // 2 passed
    			if(x>=365)y++,x-=365; // 3 passed
    			if(x>=366)assert(0);  // 4 passed (This shouldn't happen)
    			int m=1;
    			while(x-m_(m,y)>=0)x-=m_(m,y),m++;
    			int d=x+1;
    			printf("%d %d %d
    ",d,m,y);
    			continue;
    		}
    	}
    	
    //	cerr<<"
    
    Finished after "<<clock()/1000.0<<" second(s)."<<endl;
    	return 0;
    }
    
    知识共享许可协议
    若文章内无特别说明,公开文章采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
  • 相关阅读:
    团队-团队编程项目作业名称-最终程序
    《团队-中国象棋-项目总结》
    课后作业-阅读任务-阅读提问-4
    《20171130-构建之法:现代软件工程-阅读笔记4》
    《软件工程课程总结》
    《20171117-构建之法:现代软件工程-阅读笔记-3》
    -课后作业-阅读任务-阅读提问-3
    《团队-中国象棋-团队一阶段互评》
    《团队-中国象棋-开发文档》
    《结对-贪吃蛇-结对项目总结》
  • 原文地址:https://www.cnblogs.com/wallbreaker5th/p/13947440.html
Copyright © 2011-2022 走看看