题解 P2655 【2038年问题】

· · 题解

发现c++党都是先确定年份,再确定月份及以下时间,感到震惊

其实可以直接从秒开始往年推,先把秒加上最大限度的时间,再把秒化为分,以此类推

核心

计算天数时需考虑到月份和年份(每月天数不同,闰年和平年不同),所以需一次次推,天数减去当月的天数后,将月份加1,如果月份大于12,年份加1

#include <iostream>
using namespace std;
long long t,y,m,d,h,mi,s,len;//变量依次代表数据组数,年,月,天,小时,分钟,秒,时间的变量长度
long long n[33];
int mo[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
void check(){//判断闰年,并修改2月天数
    if((y%4==0&&y%100!=0)||y%400==0)
        mo[2]=29;
    else
        mo[2]=28;
}
int main(){
    int i,j;
    long long k;
    n[1]=1;//记忆化搜索,直接调用相应长度的二进制数的值
    for(i=2;i<=32;i++)
        n[i]=n[i-1]*2;
    cin>>t;
    while(t--){
        cin>>len>>y>>m>>d>>h>>mi>>s;
        s+=n[len]-1;//注意这里需要减1,因为不能计时到最大长度
        k=s/60;//化成分钟数
        s%=60;//化简后的秒数
        mi+=k;
        k=mi/60;//化成小时
        mi%=60;//化简后的分钟
        h+=k;
        k=h/24;
        h%=24;
        d+=k;
        if(m==2)//前方高能,先判断闰年
            check();
        while(d>mo[m]){
            d-=mo[m];//减去当月的天数
            m++;//月份+1
            if(m>12){//年份+1
                m=1;
                y++;
            }
            if(m==2)//月份为2时,要检查闰年和平年
                check();
        }
        cout<<y<<" "<<m<<" "<<d<<" "<<h<<" "<<mi<<" "<<s<<endl;//输出
    }
    return 0;//功德圆满
}