poj3393[模拟题]

Lucky and Good Months by Gregorian Calendar

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 1702   Accepted: 569

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 day is the amount of time the earth completes a self rotation. An year is defined to be the amount of time the earth orbits the sun. The earth takes roughly 365.242190 days to orbit the sun with some small variations. For practical purpose, a calendar year needs to have an integral number of days. Hence people need to add leap days to keep the calendar synchronized with the sun. If you keep a calendar year to have 365 years, you need to add one more day in a leap year roughly about every 4 years. However, this kind of calendar will not be in perfect synchronization with the earth’s position orbiting the sun because it advanced 365.25 days in average, which is slightly more than the actual period.

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 yy > 1582 and y ≠ 1700, is a leap year if and only if

  • y is divisible by 4, and
  • y is not divisible by 100 unless it is divisible by 400.

An year y, 0 < y < 1582 is a leap year if and only if

  • 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 month is defined to be the average time between successive new or full moons which is 29.531 days. People observe in average 12.368 full moons in an year. Unfortunately, this is also not an integral number in terms of days. Hence if we set an year to have 12 months with each month having 30 days, we need to add several days each year. To save the trouble, an alternative way is to have the number of days in a month to alternative between 30 and 31. However, this introduces one extra day. After lots of struggle, the Gregorian calendar defined the numbers of days in each month during a non-leap year to be 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, respectively from the first month to the 12th month. One more day is added on February in the leap year. The names for the months in sequence from the first month — January, February, March, April, May, June, July, August, September, October, November, and December, are also very interesting and have lots of stories associated with them. For example, the Roman Senate named the month of July after Julius Caesar to honor him for reforming their calendar. However, we do not have time to cover them here.

In ancient time, a week may have different number of days, say from 4 to 10 days. In the Gregorian calendar system, a week corresponds roughly to the moon’s quarter phase whose position can be clearly observed by people. Hence people can easily measure a week. Also for some other reasons, such as religion, it is defined as 7 days. The names of the 7 days in sequence — Sunday, Monday, Tuesday, Wednesday, Thursday, Friday and Saturday, all have interesting stories. However, we also do not have time to cover them here.

Throughout history, people believe the relative positions of the stars can decide their fate. This is also true for people living in an island T. In island T, people are working from Monday through Friday every week and enjoy holidays on every Saturday and Sunday without exceptions. There is no other holidays. From ancient tales, a month is called lucky if the last working day in this month is Friday. For examples, the last working day of September, 2006 is September 29, 2006 — which is Friday. Hence it is lucky. The last working day of July, 2006 is July 31, 2006 — which is Monday. Hence it is not lucky. The last working day of August, 2006 is August 31, 2006 — which is Thursday. Hence it is also not lucky. It is believed that if one eats only vegetable everyday during a lucky month, he/she will have a good fortune in getting rich.

Also from ancient tales, a month is called good if the first working day in this month is Monday. For examples, the first working day of July, 2006 is July 3, 2006 — which is Monday. Hence it is good. The first working day of October, 2006 is October 2, 2006 — which is Monday. Hence it is also good. The first working day of August, 2006 is August 1, 2006 — which is Tuesday. Hence it is not good. The first working day of September, 2006 is September 1, 2006 — which is Friday. Hence it is also not good. It is believed that if one goes to bed before 10 PM every day during a good month, he/she will be very healthy. A month can be both good and lucky at the same time.

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 w, 1 ≤ w ≤ 10. Then the w test cases are listed one by one. Each test case consists of 1 line with four numbers:

Ys Ms Ye Me

where two numbers are separated by a single blank, Ys is an integer, 0 < Ys < 10000, denoting the starting year in western style, Ms is an integer, 1 ≤ Ms ≤ 12, denoting the starting month, Ye is an integer, 0 < Ye < 10000, denoting the ending year in western style, Me is an integer, 1 ≤ Me ≤ 12, denoting the ending month.

Note that you can be sure the month indicated by MsYs is never after the month indicated by MeYe.

Output

For each test case, output the number of lucky months and the number of good month in between the month Ms of the year Ys (including this month) and the month Me of the year Ye (including this month) in one line. The two numbers are separated by a single blank.

Sample Input

2
2006 9 2006 9
2006 7 2006 9

Sample Output

1 0
1 1

Source

Kaohsiung 2006

大致题意:

科普文一篇,文章80%都是无用信息,因为都是常识,但是又不得不看,因为有20%是常人不知道的历史常识。

定义:

Goog month : 该月第一个工作日为星期一的月份

Luckly month: 该月最后一个工作日为星期五的月份

问: 给定一个Gregorian Calendar格里高公历的 时间闭区间(就是包括端点的年月了)

【开始年、月】~【结束年、月】

在这个时间区间内,有多少个Goog month,有多少个Luckly month

文章要点:

Gregorian Calendar格里高公历 就是现在广泛使用公历(西历),下面简称GC

GC的起始日期为 1年1月1号,该日为星期六

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了,水题

先做一个判断闰年的函数 leap()

输入时间区间的  起始年sy月sm 终止年ey月em

先计算1年1月到sy年sm-1月(若sm=1,则计算到sy-1年12月)的天数day

注意此时day的天数刚好计算到sm-1月的最后一天

若day+1,则恰好进入所输入的时间区间【开始年、月】~【结束年、月】的第一天

计算day时要注意:

(1)       1582年前后闰年判断标准改变了

(2)       1700无条件闰年

(3)       1752年9月少了11天

判断第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)       边界:若sm为Good month,计数器good++,但计数器luck不变,因为sm-1月不在时间区间内。 若计算到em为Good month,则计数器luck++,good不变,因为day一开始就+1了,当day逐月递增到em时,实则day此时为第em+1月的1号,此时判断的是em+1月是否为Good month,若是,则第em月为Luckly month,但em+1月在时间区间内,不计入计数器

(2)       逐月递增时,若到达1752年9月,要 减11天

(3)       闰年平年的月份天数不同

//#include<bits/stdc++.h>//poj不支持全能库
#include<iostream>
using namespace std;
int pmonth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年月
int rmonth[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};//闰年月
int pd(int y){//判断year是否为闰年
    if(y<1582) return !(y%4);//当year<1582时,只要能被4整除就是闰年
    else{
        if(y==1700) return 1;//当year=1700时,历史原因,无条件为闰年
        if((y%4==0&&y%100!=0)||y%400==0) return 1;//当year>=1582时,能被4整除且不被100整除为闰年,或能被400整除时为闰年
    }
    return 0;
}
int deal(int y,int m){//计算从第1年1月1日到第y年m-1月的总天数+1 (即只包括第m个月的第一天)
    int day=1;//"+1"是为了使从当月末变为下月初
    for(int i=1;i<y;i++){
        if(pd(i)) day+=366;
        else day+=365;
    }
    for(int i=1;i<m;i++){
        if(pd(y)) day+=rmonth[i];
        else day+=pmonth[i];
    }
    if(y>1752) day-=11;
    else if(y==1752&&m>9) day-=11;
    return day;
}
int main(){
    int t,*pm;cin>>t;
    while(t--){
        int sy,sm,ey,em,i,j,luck=0,good=0;
        cin>>sy>>sm>>ey>>em;
        int day=deal(sy,sm);
        if((day+5)%7<=1||(day+5)%7==6) good++;//计算起始ys年ms月1号为星期几,判断是否为good month //1年1月1号是星期六,而原本默认是星期日,因此+5调整
        for(i=sy;i<ey;i++){//计算从sy年sm+1开始 到ey-1年的月份是否为good month
            if(pd(i)) pm=rmonth;
            else pm=pmonth;
            if(i==sy) j=sm;
            else j=1;
            for(j;j<=12;j++){
                day+=pm[j];
                if(i==1752&&j==9) day-=11;
                if((day+5)%7<=1||(day+5)%7==6) good++,luck++;//由于day开始时+1缘故,当j时,计算的是第j+1月是否为good month//计算j+1月1号为星期几,判断是否为good month//当j+1月为good month,j月必为luck month
            }
        }
        if(pd(ey)) pm=rmonth;//计算第ey年的good month
        else pm=pmonth;
        if(sy==ey) j=sm;
        else j=1;
        for(j;j<=em;j++){
            day+=pm[j];
            if(i==1752&&j==9) day-=11;
            if((day+5)%7<=1||(day+5)%7==6){//同理
                if(j!=em) good++;
                luck++;
            }
        }
        cout<<luck<<‘ ‘<<good<<endl;
    }
    return 0;
}
时间: 2024-08-03 15:10:26

poj3393[模拟题]的相关文章

HDU 4028 The time of a day STL 模拟题

暴力出奇迹.. #include<stdio.h> #include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; #define ll __int64 #define N 42 ll n,m,ans;

cf428c 模拟题

这题说的是给了 n个数然后又 k次 的交换任意位置的 数字的机会  计算最长的连续子序列的和 这要撸  模拟整个 过程 并不能就是算最长的递增序列 如果只是 找最长的 和序列的 话 会存在 很多问题 在替换的时候 每一个决策 都影响着 下一个决策  这样 存在谁与谁替换 这样的状态有 200!种    那就枚举每个区间这样就可以使得 我们所用替换方法得当  因为在替换中我们进行替换是对不同区间的 操作 比如 在替换序列之内的 数字的时候 其实操作的就是不同的区间 与外面的序列进行替换的时候 操作

TOJ1290 Poker Hands 模拟题

寒假期间抽空做的一道模拟题 难度不算大,把每种牌型分开处理,可以合并的步骤考虑合并. 代码比较丑陋,首次尝试Sport Programming的风格,结果搞了个不伦不类(手动笑哭) 1 #include <algorithm> 2 #include <bitset> 3 #include <cctype> 4 #include <complex> 5 #include <cstdio> 6 #include <cstring> 7 #

hdu 5641 King&#39;s Phone(暴力模拟题)

Problem Description In a military parade, the King sees lots of new things, including an Andriod Phone. He becomes interested in the pattern lock screen. The pattern interface is a 3×3 square lattice, the three points in the first line are labeled as

HDU 2414 Chessboard Dance(模拟题,仅此纪念我的堕落)

题目 模拟题也各种wa,我最近真的堕落了,,,,,智商越来越为负数了!!!!!!!! #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; char mp[10][10]; int d=-1;//0shang,1xia,2zuo,3you int x,y;//weizhi int weizhi(int i,int j) { if(mp[i][j]=='<'){x=

HDU 4930 Fighting the Landlords(扯淡模拟题)

Fighting the Landlords 大意: 斗地主....   分别给出两把手牌,肯定都合法.每张牌大小顺序是Y (i.e. colored Joker) > X (i.e. Black & White Joker) > 2 > A (Ace) > K (King) > Q (Queen) > J (Jack) > T (10) > 9 > 8 > 7 > 6 > 5 > 4 > 3. 给你8种组合:1.

锦程网考试由试题从模拟题中批量找出答案,Python

jincin的考试又来了,像往常一样会先有模拟题发下来,而考试题目几乎都在里面原题. 本来是,在考试时,把题目一题一题地在模拟题里搜,但觉得太累了. 于是写了一个Python的脚本批量查找,用到正则,由于不知道行尾是\r还是\n还是\r\n,干脆也用正则,而非split('\r')这么硬板了. 添了颜色,效果不错. Python: 效果: - 锦程网考试由试题从模拟题中批量找出答案,Python,布布扣,bubuko.com

Codeforces 48C The Race 模拟题

题目链接:点击打开链接 题意: 给定n个加油站,一辆车由A点跑到B点,每个100m有一个加油站,每开100m需要10升油. 在每个车站会检查一下油量,若车子若开不到下一个加油站则加x升油. 开始有x升油 下面给出加油的记录. 问下一次加油在哪一站.若答案唯一输出具体哪站. 油箱容量无限 思路: 水模拟.. #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h>

FZU Problem 2034 Password table (简单模拟题)

这种简单题做了好长时间,我是不是有点逗? 地址:http://acm.fzu.edu.cn/problem.php?pid=2034 不解释了,自己看吧,练手的好题 上个代码吧 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <stdio.h> #include <string.h> #include <stdlib.h>