[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