http://acm.nbut.cn/Problem/view.xhtml?id=1271
解题报告是官方的 额自己的不知道哪里错了一直wa
本体纯数学题如果对于输入的数据直接for循环,肯定超时所以,我们得缩小运算量。该怎么办呢?输入的N为第几天。那么,我们可以先这样想: 每400年就会出现97个闰年,400年就是146097天。 我们可以先对146097求余,得到的数就是小于146097的,也就是在400年内。那么,接下来,在剩下的小于400年的里面肯定不会出现是400的整数倍的年份。那么,每100年就会有24个闰年,100年也就是36524天。我们对36524求余,得到的数就是小于36524的,也就是在100年内了。接着,在剩下的小于100年的里面肯定不会出现100的整数倍的年份。那么,每4年就会有一个闰年,4年也就是1461天。我们对1461求余,得到的数就是小于1461的,也就是在4年了。然后,在剩下的小于4年的里面,前三年肯定不会出现闰年。我们对365求余,剩下来的数肯定是小于365的。你看,我们只要简单的四个步骤就把那么大的一个数字控制在1年内了。在把最后的一年计算一下就可以了(注意区分该年是闰年还是平年哦)。
#include <iostream>
using namespace std;
int mon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int mo[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int main()
{
int i, n, year, month, day, p;
while(~scanf("%d", &n))
{
p = 0;
day = n;
year = month = 1;
if(n % 146097 == 0)
{
/*
假设n=146097的倍数;那么此时 由于1月1日是第一天 那么第n天日期一定是 400*k+399 年, 12 月 ,31 日
除了前k个400年,剩余的天数为146097 对应399 12 31 我们不好处理 因此只在下面的步骤中找出k个400年
剩余的单独处理 所以要n-- p记录n--的次数 后面还要加上
*/
n--;
p++;
}
year += n / 146097 * 400;
n %= 146097;
if(n % 36524 == 0)
{
n--;
p++;
}
year += n / 36524 * 100;
n %= 36524;
if(n % 1461 == 0)
{
n--;
p++;
}
year += n / 1461 * 4;
n %= 1461;
if(n % 365 == 0)
{
n--;
p++;
}
year += n / 365;
n %= 365;
i = 0;
if(year % 400 == 0 || year % 4 == 0 && year % 100 != 0)
{
while(n - mo[i] > 0)
{
month++;
n -= mo[i];
i++;
}
}
else while(n - mon[i] > 0)
{
month++;
n -= mon[i];
i++;
}
n += p;
printf("%d %d %d\n", year, month, n);
}
return 0;
}