Description
Have you ever wondered why normally an year has 365 days, not 400 days? Why August have 31 days, but February have only 28 days? Why there are 7 days, not 6 days, in a week? Do people in ancient time use the same calendar as we do? There are many interesting conjectures and theories about those problems. Now we will tell you one story that may help explaining plausible answers to these questions. Using information in the story, you are then ask to solve an interesting problem using computer. Note that there are many theories about the calendar system discussed. This problem set will tell only one of them in a simplified way.
Throughout history, people keep track of time by observing the relative positions of the earth, the moon and the sun. A
Depending on how accurate you can measure the period of the earth orbiting the sun, you need to invent different formulas for leap years. Several famous Western calendar systems have been invented, not to mention the more complex Oriental systems. In order to save programmers’ efforts, we will not discuss the Oriental, such as Chinese, calendar systems. We will focus on major Western calendar systems. The earliest one may be the Julian calendar created by Julius Caesar in 46 BC. It is not accurate enough and will have one day off every 128 years. The next one is the Astronomical Julian calendar invented by Joseph Justus Scaliger around the 16th century. Both have simple formulas to determine which year is a leap year.
The next major one is called Gregorian calendar that was invented at the year 1582 because the synchronization of the earth’s orbiting and the calendar is finally noticed by people. In this system, a leap year is dropped every 100 years unless it is every 400 years. By doing this modification, the average number of days in a calendar year is 365.2425. Note that this system is also not perfect. It adds one more day every 3289 years. There are other more modifications suggested, such as the one by Astronomer John Herschel, the Greek Orthodox, and the SPAWAR group in the US Navy. For simplicity, people use Gregorian calendar system though it may not be perfect.
The following is the formula for the Gregorian calendar to determine whether an year is a leap year or not. An year
-
y
is divisible by 4, and -
y
is not divisible by 100 unless it is divisible by 400.
An year
- y
is divisible by 4.
Hence year 4 is a leap year, year 100 is a leap year, year 1900 is not a leap year, but year 2000 is a leap year. A leap year has 366 days with the extra day February 29. A non-leap year has 365 days.
During your computation, you may also want to observe the following facts about Gregorian calendar. Many calendar systems were used by people in different areas in the Western world at the same time. The current Western calendar system, primarily follows Gregorian calendar, and is so called the Gregorian Reformation, was adopted by Britain and the possessions on September 3, 1752. For lots of reasons that we are sure you do not want to read in this problem description, 11 days are eliminated starting September 3, 1752 in order for people not to rewrite history. That is, in the Gregorian calendar, there is no days in between September 3, 1752 and September 13, 1752. Note that Rome adopted the Gregorian calendar at the year 1582, when it was invented. Also for historical reasons, the year 1700 is declared a leap year in the Gregorian calendar. There are other variations about the Gregorian calendar system, however, we will use the one that is defined above.
A lunar
In ancient time, a
Throughout history, people believe the relative positions of the stars can decide their fate. This is also true for people living in an island
Also from ancient tales, a month is called
Given a period of time, your task is to report the number of lucky months and the number good months during this period of time using the described Gregorian calendar system.
Input
The first line contains the number of test cases
Ys
where two numbers are separated by a single blank,
Note that you can be sure the month indicated by
Output
For each test case, output the number of lucky months and the number of good month in between the month
Sample Input
2 2006 9 2006 9 2006 7 2006 9
Sample Output
1 0 1 1
大致题意:
科普文一篇,文章80%都是无用信息,因为都是常识,但是又不得不看,因为有20%是常人不知道的历史常识。
定义:
Goog month
Luckly month:该月最后一个工作日为星期五的月份
问:给定一个Gregorian Calendar格里高公历的时间闭区间(就是包括端点的年月了)
【开始年、月】~【结束年、月】
文章要点:
Gregorian Calendar格里高公历就是现在广泛使用公历(西历),下面简称GC
GC的起始日期为
GC平年有365天,闰年366天(2月多1天)
GC有12个月,各月的天数和现在的使用的西历一致
GC在1582年之前(不包括1582),若该年份能被4整除,则为闰年
GC在1582年之后(包括1582),判断闰年的标准(满足下面随便一个):
(1)能被4整除,但不能被100整除;
(2)能被400整除。
由于历史原因,GC规定1700年无条件为闰年
由于历史原因,GC规定1752年9月3日~13日共11天不存在,即1752年9月只有19天
GC一星期有7天,排序为Sun,Mon,Tue,Wed,Thu,Fri,Sat,和现在的星期一致,其中Mon到Fri为工作日,Sun和Sat为休息日
解题思路:
直接模拟就OK了,水题
先做一个判断闰年的函数
输入时间区间的
先计算1年1月到sy年sm-1月(若sm=1,则计算到sy-1年12月)的天数day
注意此时day的天数刚好计算到sm-1月的最后一天
若day+1,则恰好进入所输入的时间区间【开始年、月】~【结束年、月】的第一天
计算day时要注意:
(1)
(2)
(3)
判断第day天是星期几:
由于1年1月1号为星期六,一星期有7天,
因此(day+5)%7就能计算第day天是星期几。
不能直接day%7,day%7就是默认1年1月1号为星期日,至于为什么要先+5,这个不难推导,读者自己想想就明白了
判断某月是不是Good month和Luckly month:
计算天数day后,令day++,进入sm的1号
此时判断sm的1号是不是为Good month,使用上面给出计算第day天是星期几的方法,若
1号为星期日(0)、星期六(6)或星期一(1),则该月为Good month
从sm月开始,把天数day逐月递增,逐月判断该月是否为Good month,判断方法都是一样的。
不难发现,若第k月为Good month,则第k-1月必定为Luckly month,因此两个计数器同时增加即可。
注意3点:
(1)
(2)
代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cstdio>
#include <cmath>
#include <string>
#include <stack>
using namespace std;
int Month[14]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
int Lmonth[14]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
enum week {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
bool leap(int year)//判断闰年,是闰年则返回true。反之则反回faslse
{
if(year<1582)
return !(year%4);
else
{
if(year==1700)
return true;
if((!(year%4)&&(year0)) || !(year@0))
return true;
}
return false;
}
int ComputeDay(int y,int m)//计算从1年1月到y年m月的天数
{
int i,j,day=1;
for(i=1; i<y; i++)
if(leap(i))
day+=366;
else
day+=365;
for(j=1; j<m; j++)
if(leap(i))
day+=Lmonth[j];
else
day+=Month[j];
if(y>1752)
day-=11;
else if(y==1752 && m>9)
day-=11;
return day;
}
int main()
{
int i,j,k;
int *pm;
int test;
cin>>test;
while(test--)
{
int ys,ms,ye,me;
cin>>ys>>ms>>ye>>me;
int luck=0;
int good=0;
int day=ComputeDay(ys,ms);
// printf("%d\n",day);
if(((day+5)%7<=Mon) || ((day+5)%7==Sat))
good++;
for(i=ys; i<ye; i++)
{
if(leap(i))
pm=Lmonth;
else
pm=Month;
if(i==ys)
j=ms;
else
j=1;
for( ; j<=12; j++)
{
day+=*(pm+j);
if(i==1752 && j==9)
day-=11;
if(((day+5)%7<=Mon) || ((day+5)%7==Sat))
{
good++;
luck++;
}
}
}
if(leap(i))
pm=Lmonth;
else
pm=Month;
if(i==ys)
j=ms;
else
j=1;
for(; j<=me; j++)
{
day+=*(pm+j);
if(i==1752 && j==9)
day-=11;
if(((day+5)%7<=Mon) || ((day+5)%7==Sat))
{
if(j!=me)
good++;
luck++;
}
}
cout<<luck<<' '<<good<<endl;
}
return 0;
}