zoukankan      html  css  js  c++  java
  • [CSP-S2020]儒略日 题解

    题意分析

    给出距离 4713.1.1 B.C 的天数,要求计算出具体的日期

    思路分析

    显然,模拟即可。考虑根据历法的分为不同的阶段进行计算,然后从大周期到小周期进行处理。

    可以将最特殊的 1582 年单独分为一段,它之前的分为一段,它之后的分为一段。

    对于第一段(1581-),最大的周期即为四年(四年一闰),因此以四年为周期划分;对于每个四年周期内,以一年为周期划分;对于每个一年周期内,以一月为周期划分;然后处理天数即可。由于 4713 B.C 刚好为闰年,因此从头开始划分即可。注意公元前和公元后的判断。

    对于第二段(1582),按月划分,特判 10 月的 10 天缺失即可。

    对于第三段(1583+),最大的周期为四百年(世纪年四次一闰),接下来为一百年,然后为四年、一年、一月,依次划分即可。因为最开始不满一个周期,因此可以接着划分成 1583 , 1584-1599 ,1600+ 三段,第一段按一年的最大周期处理,第二段按四年的最大周期处理,第三段按四百年的最大周期处理即可。注意世纪年的特殊闰年处理。

    细节比较多,注意不同阶段和周期对应的数值。

    考场代码,有些地方可能比较乱,见谅。

    //FJ-00445
    //NOIP2020 RP++
    #include<iostream>
    #include<cstdio>
    #define ll long long
    using namespace std;
    int T;
    int mp[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年的一月周期
    int mr[12]={31,29,31,30,31,30,31,31,30,31,30,31};//闰年的一月周期
    int sp[12]={31,28,31,30,31,30,31,31,30,21,30,31};//1582的一月周期
    int yp[4]={366,365,365,365};//一年周期
    ll n,ans;
    void solve1()//1581-
    {
        ans=n/1461*4;n%=1461;ll p,q;//四年周期
        for(p=0;p<4 && n>=yp[p];p++)
            n-=yp[p],ans++;//一年周期
        if(!p)//第一年为闰年
            for(q=0;q<12 && n>=mr[q];q++)
                n-=mr[q];//闰年的一月周期
        else
            for(q=0;q<12 && n>=mp[q];q++)
                n-=mp[q];//平年的一月周期
        if(ans<4713)
            printf("%lld %lld %lld BC
    ",n+1,q+1,4713-ans);//公元前
        else
            printf("%lld %lld %lld
    ",n+1,q+1,ans-4713+1);//公元后
    }
    void solve2()//1583+
    {
        n-=2299239;ans=1583;ll p,q;//快进到1583
        if(n<365)//1583 
            for(q=0;q<12 && n>=mp[q];q++)
                n-=mp[q];//平年的一月周期
        else
            if(n<6209)//1584-1599
            {
                n-=365;ans++;//快进到1584
                ans+=n/1461*4;n%=1461;
                for(p=0;p<4 && n>=yp[p];p++)
                    n-=yp[p],ans++;
                if(!p)
                    for(q=0;q<12 && n>=mr[q];q++)
                        n-=mr[q];
                else
                    for(q=0;q<12 && n>=mp[q];q++)
                        n-=mp[q];
            }
            else//1600+
            {
                n-=6209;ans=1600;//快进到1600
                ans+=n/146097*400;n%=146097;//四百年周期
                if(n<366)//只有第一个世纪年为闰年
                    for(q=0;q<12 && n>=mr[q];q++)
                        n-=mr[q];
                else/
                {
                    n--;//假装是第一个世纪年是平年,按照一般的一百年周期计算
                    ans+=n/36524*100;n%=36524;//一百年周期
                    if(n<365)//其余的世纪年均为平年
                        for(q=0;q<12 && n>=mp[q];q++)
                            n-=mp[q];
                    else
                    {
                        n++;//假装世纪年为闰年,按照一般的四年周期计算
                        ans+=n/1461*4;n%=1461;
                        for(p=0;p<4 && n>=yp[p];p++)
                            n-=yp[p],ans++;
                        if(!p)
                            for(q=0;q<12 && n>=mr[q];q++)
                                n-=mr[q];
                        else
                            for(q=0;q<12 && n>=mp[q];q++)
                                n-=mp[q];
                    }
                }
            }
        printf("%lld %lld %lld
    ",n+1,q+1,ans);
    }
    void solve3()//1582
    {
        n-=2298884;ans=1582;ll q;//快进到1582
        for(q=0;q<12 && n>=sp[q];q++)
            n-=sp[q]; 
        if(q==9 && n>3)//10月特判
            n+=10;
        printf("%lld %lld %lld
    ",n+1,q+1,ans);
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%lld",&n);
            if(n<2298884)
                solve1();
            else
                if(n>2299238)
                    solve2();
                else
                    solve3();
        }
        return 0;
    }

    下面给出一些数值的计算式:

    • 四年周期: $366+365+365+365=1461$ ,即一个闰年加三个平年
    • 一百年周期: $1461×frac{100}{4}-1=36524$ ,即 $25$ 个四年周期减掉平年世纪年
    • 四百年周期: $36524×frac{400}{100}+1=146097$ ,即 $4$ 个一百年周期加上闰年世纪年
    • 快进到 1582 :$1461× left lfloor frac{4713+1581}{4} ight floor +366+365= 2298884$ ,即 4713 B.C - 1581 A.D 的所有完整的四年周期加上 1580,1581 两年
    • 快进到 1583:$2298884+355=2299239$ ,即在 1582 年的基础上加上 1582 一年
    • 快进到 1600:$1461×frac{1600-1584}{4}+365=6209$ ,即 1584-1599 四个完整的四年周期加上 1583 一年

     

  • 相关阅读:
    IOSUITextField类
    IOSUITableView设置背景图片,方式与众不同。
    IOS图标知识详情(转载自http://luoyl.info/blog/2012/03/iphoneipadicons/)
    IOSCreate UIActionSheet 'otherButtons' by passing in array
    Offset文件名(绝对偏移量)
    单例模式(Singleton)Holder
    在 spring 中一共定义了七种事务传播属性
    UML,各种关系合集
    Java,线程池,ThreadPoolExecutor
    EasyMock
  • 原文地址:https://www.cnblogs.com/TEoS/p/13956068.html
Copyright © 2011-2022 走看看