定义:
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天
思路很简单,只需要计算出当前这个月的第一天是不是星期五到星期天之间的一天就可以了。
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <algorithm> using namespace std; int mon[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; bool judge(int y) { if(y == 1752) mon[9] = 19; else mon[9] = 30; if(y == 1700) return true; if(y < 1582) { if(y%4 == 0) return true; return false; } if( (y%4 == 0 && y%100 != 0) || y%400 == 0) return true; return false; } int main() { int T; int sl,sg; int ys,ms,ye,me; int i,j; unsigned long long sd; scanf("%d",&T); while(T--) { scanf("%d %d %d %d",&ys,&ms,&ye,&me); sd = 0; sl = 0; sg = 0; for(i = 1; i < ys; ++i) { if(judge(i)) sd += 366; else sd += 365; if(i == 1752) sd -= 11; } if(judge(ys)) mon[2] = 29; else mon[2] = 28; for(i = 1; i < ms; ++i) { sd += mon[i]; } if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sg++; } sd += mon[ms]; if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sl++; } if(ys == ye) { for(i = ms+1; i <= me; ++i) { if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sg++; } sd += mon[i]; if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sl++; } } } else { for(i = ms+1; i <= 12; ++i) { if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sg++; } sd += mon[i]; if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sl++; } } for(j = ys+1; j < ye; ++j) { if(judge(j)) mon[2] = 29; else mon[2] = 28; for(i = 1; i <= 12; ++i) { if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sg++; } sd += mon[i]; if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sl++; } } } if(judge(ye)) mon[2] = 29; else mon[2] = 28; for(i = 1; i <= me; ++i) { if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sg++; } sd += mon[i]; if((sd+5)%7 == 0 || (sd+5)%7 == 6 || (sd+5)%7 == 5) { sl++; } } } printf("%d %d\n",sl,sg); } return 0; }