分析:
本题涉及到星期数的计算,即根据公历日期(年、月、日)推算出星期几。首先约定用数字代表星期几,这些数字称为星期数。比如,可以约定星期一到星期日为1~7。给定公历日期,可以采用基姆拉尔森公式或蔡勒公式计算星期数。但这两个公式都非常复杂,很难记住
计算星期数还有一种方法:根据一个基准日期的星期数来推算给定日期的星期数。例如,在本题中,我们可以查一下,2009年11月11日是星期三。已知某个基准日期的星期数为w,以及自基准日期到给定日期的天数是t(给定日期在基准日期之后)则求给定日期的星期数直接利用取余运算即可。取余的式子本来是(w+t)%7,但对7取余落入范围[0,6],与前面约定的星期数取值范围不一致,所以要加1,为了抵消加1的效果,取余之前先减1,因此正确的计算式子是:(w+t-1)%7+1
如果给定日期在基准日期之前,且从给定日期到基准日期的天数是,则计算公式为((w-t-1)%7+7)%7+1。注意,第一次取余运算结果可能为负数,所以加7再取余。
在本题中,假设已知去年11月11日的星期数为W,如果今年是闰年,则今年11月11日的星期数为(w+366-1)%7+1;否则,即今年是平年,则今年11月11日的星期数为(w+365-1)%7+1
因此,我们可以从2009年11月11日的星期数w为3,推算出x年11月11日的星期数。然后再枚举[x,y)范围内的每个年份,计算出每年11月11日的星期数w,如果w为1,则计数。本题需要多次判断一个年份是否为闰年,所以定义Ieap函数实现
本题还需要处理多个测试数据。每个测试数据为x,y。当x和y为0时,输入结束。可以用永真循环while(1)实现:先读入x和y,如果x和y为0,则用break语句退出while循环
代码如下:
#include<iostream>
using namespace std;
int leap(int year){ //判断是否为闰年
if(year%400==0 or (year%4==0 and year%100!=0))
return 1;
else return 0;
}
int main()
{
int x, y, year, cnt;
while(1){
cin >> x >> y;
if(x==0 and y==0) break; //输入结束
cnt = 0;
int w = 3; //2009年11月11日是星期三
//先算出×年11月11日是星期几
for(year=2010; year<=x; year++){
if(leap(year)) w = (w+366-1)%7+1;
else w = (w+365-1)%7+1;
}
for(year=x; year<y; year++){ //枚举[x,y)每个年份
if (w==1) cnt++;
if(leap(year+1)) w = (w+366-1)%7+1; //计算下一年11月11日是星期几
else w = (w+365-1)%7+1;
}
cout << cnt << endl;
}
return 0;
}