法1:

我的想法及其简单

根据当前的年月日,求出本年度度过了多长时间

随后加到跳过天数上

所得到的跳过天数,就是从一年的起始处开始算起的

再求出,这是第几年,减去中间各年度过的时间

即得到了对应年,已经对应年度过的时间

随后根据对应年和对应年度过时间,求出其日期

#include <bits/stdc++.h>
using namespace std;

static int BeforeThisMonth[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

void NewMandD(const int &Y,int &M,int &D,int &RestDays)
{//用于确定,在当前的年和跳过的天数下,月和日是多少
    int isRunNian = 0;
    if ((!(Y % 4) && Y % 100) || !(Y % 400))
        isRunNian = 1;
    if (isRunNian && RestDays > 60)
        RestDays--;
    for(int i=0;;i++)
    {
        if(RestDays<=BeforeThisMonth[i])
        {
            M=i;
            break;
        }
    }
    D = RestDays - BeforeThisMonth[M - 1];
}
    
int WhichYear(int Y,int &NewDays,int &RestDays)
{//用于确定,现在是第几年
    int tempY=Y;
    for(int i=Y;;Y++)
    {
        if(!(Y%4)&&Y%100||!(Y%400))
        {
            if(NewDays>366)
                NewDays-=366;
            else
            {
                RestDays=NewDays;
                return Y;
            }
        }
        else
        {
            if(NewDays>365)
                NewDays-=365;
            else
            {
                RestDays=NewDays;
                return Y;
            }
        }
    }
}

int PastDaysThisY(const int &Y,const int &M,const int &D)
{//用于确定,在当前的年月日下,一年过去了几天
    int isRunNian=0;
    if(!(Y%4)&&Y%100||!(Y%400))
        isRunNian=1;
    if (M >= 3 && isRunNian == 1)
        return BeforeThisMonth[M - 1] + D + 1;
    else
        return BeforeThisMonth[M - 1] + D;
}

void Leapdays(int &Y,int &M,int &D,const int &Leap)
{//用于确定跳过了Leap天后最终的年月日
    int Past=PastDaysThisY(Y,M,D);
    int NewDays=Leap+Past;
    int RestDays=0;
    Y=WhichYear(Y,NewDays,RestDays);
    NewMandD(Y,M,D,RestDays);
}

void PrintDate(const int &Y,const int &M,const int &D)
{
    printf("%04d-%02d-%02d\n",Y,M,D);
//     cout << Y << '-';
//     if (M >= 10)
//         cout << M;
//     else
//         cout << '0' << M;
//     if (D >= 10)
//         cout << '-' << D << endl;
//     else
//         cout << "-0" << D << endl;
}

int main()
{
    int Times=0;
    int Y,M,D,Leap;
    cin>>Times;
    for(int z=0;z<Times;z++)
    {
        cin>>Y>>M>>D>>Leap;
        Leapdays(Y,M,D,Leap);
//         PrintDate(Y,M,D);
        printf("%04d-%02d-%02d\n",Y,M,D);
    }
    return 0;
}

法2:

本方法就是将平闰年的各月的天数矩阵列出

随后也将平闰年的天数放入矩阵中

有两种关键操作

其一是将对应的日期转换为当前年经过多少天:

该操作是遍历对应的平闰年的对应行矩阵

将本月之前的各月份的矩阵加起来,并且加上当前的几号,就是当年过去的天数

其二是将当年过了多少天,转换为对应的日期

该操作是从1月开始遍历

在遍历的过程中有一个判断,若leap第一次小于等于当前的月份值,则得到几月,多余的天数则是几号,则跳出

若leap大于当前月份值,则将其减去对应月的天数,继续循环

#include <stdio.h>
#include <string.h>

//此处是平年和闰年的各月份的矩阵
int Month[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
//此处是平年和闰年的一年的总时间
int Year[2] = {365, 366};

int main()
{
    int year, month, day, leap, repeat;
    scanf("%d", &repeat);
    while (repeat--)
    { //到此处,得到了循环总数
        scanf("%d%d%d%d", &year, &month, &day, &leap);
        //到此处得到了年月日,以及即将跳过的时间

        int y;
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
            y = 1;
        else
            y = 0;
        //以上即确定了当前年度的平闰年

        for (int i = 0; i < month; i++)
        {
            leap += Month[y][i];
        }
        leap += day;
        //以上即将本年度已经经过的时间全部加上了
        //得到的新的leap是从本年的开始向后跳的

        for (int i = year;; i++)
        { //此处for循环,可以求得最终的年数
            if ((i % 4 == 0 && i % 100 != 0) || (i % 400 == 0))
                y = 1;
            else
                y = 0;
            //以上即确定了当前年度i的平闰年

            if (leap > Year[y])
                leap -= Year[y];
            //若不是最终年,则继续循环
            else
            {//在最终年的话,则跳出循环
                month = 1;
                while (leap > Month[y][month])
                {//求出当前年的月份
                    leap -= Month[y][month];
                    month++;
                }
                day = leap;
                year = i;
                break;
            }
        }
        printf("%04d-%02d-%02d\n", year, month, day);
    }
    return 0;
}