《星期几》 蓝桥杯复赛试题

题目描述

【结果填空】 (满分5分)

    1949年的国庆节(10月1日)是星期六。 

    今年(2012)的国庆节是星期一。

    那么,从建国到现在,有几次国庆节正好是星期日呢?

    只要答案,不限手段!
    可以用windows日历,windows计算器,Excel公式,。。。。。
    当然,也可以编程!

    不要求写出具体是哪些年,只要一个数目!
    千万不要提交源代码!


思路分析

这不是一道存粹的编程题目,作为一道填空题目,也不会有负责的数据结构,我们结合数学,分布解决之。

对于星期几,这明显是一个周期函数,即:f(x+T) = f(x)  其中,T = 7.

一个很直接的思路就是:用from 1940-10-1 to year-10-1的天数除以7,如果余数为1,则该年的国庆节是星期天。

即:f(6 + n*T + 1) = f(7)

但是,该方法有一个明显的缺点就是要计算n*T并不是很简单,而且随着年份的增大,这个数字也会越来越大,直到不能存储,所以需要进行优化。

优化的思路很简单,其实我们没有必要揪着1949年的国庆节不放,假设我们知道2000年的某一天使星期几的话,我们还用减去1949年的国庆节吗?很明显不用,这就是优化的原理。

假设赵国庆出生于1949年10月1日,那么他到1950年10月1日的时候,是不是该过生日了?哈哈,没错,正好一年!那么这一年是365还是366天呢?这取决是1950年是平年还是闰年。


1949年的国庆假是星期六,即:f(6)

设这一年的总天数为x,则若x为平年,则x=365,若x为闰年,则y=366.

算到这里,我们需要一个判断平年闰年的函数:

int judge(int year)		//用于判断平年,闰年的函数 
{
	if(year%400==0 || year%4==0 && year%100 !=0)
	{
		return 366;
	}
	else
	{
		return 365;
	}
} 

x / 7 = a ……b;

对于1949年的国庆节,f = f( t1949 ) = f(6)

对于1950年的国庆节,f = f(t1950) =  f(t1949 + a*T +b) = f( (t1949+b)%7 )

对于1951年的国庆节,f = f(t1951) =  f(t1950 + a*T +b) = f( (t1950+b)%7 )

……

得到一般结论f = f(tyear) = f(t(year-1) + a*T + b) = f(  (t(year-1) + b)%7)

编写代码

#include<iostream>
using namespace std;
int judge(int year)		//用于判断平年,闰年的函数 
{
	if(year%400==0 || year%4==0 && year%100 !=0)
	{
		return 366;
	}
	else
	{
		return 365;
	}
} 
int main()
{
	int counter = 0;
	int w = 6;
	for(int year=1950;year<2013;year++)
	{
		w = (judge(year)%7 + w)%7 ;
		if(0 == w)
		{
			//cout<<year<<endl;
			counter++;
		}
	}
	cout<<counter<<endl;
	return 0;
} 

说明:
judge(year)%7对应思路分析中的b,经过分析可以发现7的倍数a其实是用不到的,然后w对应思路分析中的t,当这一年的国庆节是星期天的时候,对应得t为0,因为7可以被7整除。
注释部分输出对应的年份,便于调试。

输出结果:
1950
1961
1967
1972
1978
1989
1995
2000
2006
9


posted @ 2014-05-24 21:07  千手宇智波  阅读(272)  评论(0编辑  收藏  举报