P7075 儒略日

解题方法

考场爆零qaq

  • 这是一道大模拟题 (先问候出题人之母为敬), 首先考虑暴力算法 , 也就是从公元前 4713 年 1 月 1 日开始 , 一天一天地往后枚举 , 时间复杂度 \(O(Q\times Day)\) , 期望得分 : 30-40 pts 。

  • 接下来考虑正解 。弱智算法思路

  • 从公元前 4713 年 1 月 1 日到公元前 1 年 12 月 31 日 ( 0 天到 1721423 天 ) , 四年 (1461 天 ) 分为一组 , 最后不满一组的剩余天数按照 闰年 , 平年 , 平年 , 平年 的顺序特判 , 再枚举 12 个月份 。( 这么分是因为这一部分的后面都要输出一个 BC , 懒就完了 )

  • 从公元元年 1 月 1 日到公元 1582 年 10 月 4 日 (1721425 天到 2299160 天) , 和剩余的条件 1 的算法相同 。

  • 从公元 1582 年 10 月 15 日到公元 1599 年 12 月 31 日 , ( 2299162 天到 2305447 天 ) , 一天一天地往后枚举即可 ( 也是为了后面的步骤方便 ,懒就完了 ) 。

  • 公元 1600 年 1 月 1 日之后 ( 大于等于2305448 天 ) , 四百年 ( 146097 天 ) 分为一组 , 最后不满一组的天数按照 闰年 , 平年 , 平年 , 平年 …… 的顺序特判 , 再枚举 12 个月份 。

  • 时间复杂度 \(O(Q)\) , 期望得分 100 pts ( 记得开long long )。

实现代码(Made by 天帝)

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
long long Q,day;
int RunNian[450],MONTH[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
    for(int i=0;i<=400;i+=4)
        RunNian[i]=1;
    for(int i=100;i<=400;i+=100)
        RunNian[i]=0;
    scanf("%lld",&Q);
    while(Q--)
    {
        scanf("%lld",&day);
        if(day<=1721423) // TO 12 31 1 BC
        {
            // "这里"
            int flag=0,year=day/1461,month=0; // 四年一次
            day-=year*1461;
            year*=4,year-=4713;
            day++; // 请读者自行思考为什么要在这里 day++ , 而不在  "这里"  day++ ( 后面有解释 )
            if(day>366)
            {
                flag=1,day-=366,year++;
                if(day>365)
                {
                    day-=365,year++;
                    if(day>365)
                        day-=365,year++;
                }
            }
            MONTH[2]=28;
            if(!flag)
                MONTH[2]=29;
            for(int i=1;i<=12;i++)
            {
                if(day-MONTH[i]>=1) // 有剩余天数 
                    day-=MONTH[i],month=i;
                else break;
            }
            month++;
            printf("%d %d %d BC\n",day,month,abs(year));
        }
        else if(day==1721424)
            printf("1 1 1\n");
        else if(1721424<day && day<=2299160) // TO 4 10 1582
        {
            day-=1721424; // "上面" 
            int flag=0,year=day/1461,month=0; // 四年一次
            day-=year*1461;
            year*=4,year++;
            day++; // 请读者自行思考为什么在 "上面" 不一起把 day++ 了 
            if(day>365)
            {
                day-=365,year++;
                if(day>365)
                {
                    day-=365,year++;
                    if(day>365)
                        flag=1,day-=365,year++;
                }
            }
            MONTH[2]=28;
            if(flag)
                MONTH[2]=29;
            for(int i=1;i<=12;i++)
            {
                if(day-MONTH[i]>=1) // 有剩余天数 
                    day-=MONTH[i],month=i;
                else break;
            }
            month++;
            printf("%d %d %d\n",day,month,year);
        }
        else if(day==2299161)
            printf("15 10 1582\n");
        else if(2299161<day && day<=2305447) // TO : 1599 12 31
        {
            day-=2299161;
            int year=1582,month=10,DAY=15;
            for(int i=1;i<=day;i++)
            {
                DAY++,MONTH[2]=28;
                if(month==2 && year%4==0)
                    MONTH[2]=29;
                if(DAY>MONTH[month])
                    DAY=1,month++;
                if(month>12)
                    month=1,year++;
            }
            printf("%d %d %d\n",DAY,month,year);
        }
        else if(2305448<=day) // FROM : 1600 1 1
        {
            day-=2305448;
            long long flag=0,year=day/146097,month=0; // 400年为146098 
            day-=year*146097;
            year*=400,year+=1600;
            day++;
            for(int i=0;i<=399;i++)
            {
                flag=RunNian[i];
                if(day-365-RunNian[i]>=1)
                    day=day-365-RunNian[i],year++;
                else break;
            }
            MONTH[2]=28;
            if(flag)
                MONTH[2]=29;
            for(int i=1;i<=12;i++)
            {
                if(day-MONTH[i]>=1) // 有剩余天数 
                    day-=MONTH[i],month=i;
                else break;
            }
            month++;
            printf("%lld %lld %lld\n",day,month,year);
        }
    }
    return 0;
}
posted @ 2021-10-16 16:59  青D  阅读(84)  评论(0)    收藏  举报