宁波工程学院 [1271] Nth Day is Which Day 输出第n天的日期 (要求算法很快速,解决超时)

  • [1271] Nth Day is Which Day

  • 时间限制: 1000 ms 内存限制: 65535 K
  • 问题描述
  • The first day is 1 year 1 month 1 day, so the Nth day is which day?
  • 输入
  • Input until EOF.
    Input a positive integer N means the Nth day(0<N<365000).
  • 输出
  • You should output the date of that day(year month day).
  • 样例输入
  • 1
    2
    32
    
  • 样例输出
  • 1 1 1
    1 1 2
    1 2 1
    
  • 提示
  • 来源
  • hungar
    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;
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值