[Project Euler] 来做欧拉项目练习题吧: 题目019

                            [Project Euler] 来做欧拉项目练习题吧: 题目019

                                              周银辉 

 

题目描述:

You are given the following information, but you may prefer to do some research for yourself.

  • 1 Jan 1900 was a Monday.
  • Thirty days has September,
    April, June and November.
    All the rest have thirty-one,
    Saving February alone,
    Which has twenty-eight, rain or shine.
    And on leap years, twenty-nine.
  • A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.

How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)? 

 

问题分析:

计算从1901年到2000年间,有多少个星期天是在月初。

题目说1900年1月1日是星期一,也就是说1900年1月7日是星期天,那么从这天开始每增加7天都是星期天。

然后问题就转换成了这些星期天中哪些是在月初。

高级语言都内置了日期函数,如果用类似于date.addDays(n)之类的函数,这个问题就变得非常简单了。

不使用内置函数的话,就用下面的get_days和get_date方法吧:

#include <stdio.h>
long get_days(long y, long m, long d)
{
m = (m + 9)%12;                /* mar=0, feb=11 */
y = y - m/10;                  /* if Jan/Feb, year-- */
return y*365 + y/4 - y/100 + y/400 + (m*306 + 5)/10 + (d - 1);
}
void get_date(long days, long* y, long* m, long* d)
{
long yy, ddd, mm, dd, mi;
yy = (10000*days + 14780)/3652425;
ddd = days - (yy*365 + yy/4 - yy/100 + yy/400);
 
if (ddd < 0) 
{
yy--;
ddd = days - (yy*365 + yy/4 - yy/100 + yy/400);
}
mi = (52 + 100*ddd)/3060;
 
*y = yy + (mi + 2)/12;
*m = (mi + 2)%12 + 1;
*d = ddd - (mi*306 + 5)/10 + 1;
}
int main()
{
long count = 0;
long year  = 1900;
long month;
long day;
long days = get_days(1900, 1, 7);
while(1)
{
days += 7; //增加7天,肯定是星期天
//取得该天的日期,判断其是否是1号
get_date(days, &year, &month, &day);
//printf("%ld-%ld-%ld\n", year, month, day);
if (year>2000) 
{
break;
}

 

if(day==1 && year>=1901)
{
//今天是1号,那么至少要等28天以后才可能是1号了,下次循环是要加7天,所以这里加21天
//避免无用的运算
days  += 21; 
count ++;
}
}
printf("total count %ld\n", count);
return 0;

 

此题几乎不需要多少时间:

real    0m0.005s
user    0m0.001s
sys     0m0.003s 

posted @ 2011-04-19 20:38  周银辉  阅读(2410)  评论(8编辑  收藏