题目:
http://poj.org/problem?id=3393
题意:
很长的阅读题,要点有以下几点:
- 1752年9月3日~13日共11天不存在。
- 1582年之前(不包括1582)判断闰年的方式是能被4整除
- 1582年及以后判断闰年的方式就是我们常用的:能被400整除,或者能被4整除且不能被100整除
- 1700规定为闰年。
- 每个月的第一个工作日是星期一,这个月就是good month
- 每个月的最后一个工作日是星期五,这个月就是luck month
最后,求给定的时间段内good month和luck month的个数
思路:
模拟,打表,没什么好说的,就是题意十分恶心
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 10010;
int Luck[N][13], Good[N][13];
int day[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool leap(int y)
{
if(y == 1700) return true;
if(y < 1592)
{
return y % 4 == 0;
}
else
{
if((y % 400 == 0) || (y % 100 != 0 && y % 4 == 0)) return true;
else return false;
}
}
void table()
{
int tm = 5;//首先写个程序计算出公元1年1日为周六,这里赋值为前一天,即星期五
memset(Good, 0, sizeof Good);
memset(Luck, 0, sizeof Luck);
//打表计算,把所有的good和luck计算出来
for(int i = 1; i <= 10000; i++)
{
for(int j = 1; j <= 12; j++)
{
int d = day[j];
if(j == 2 && leap(i)) d++;
for(int k = 1; k <= d;)
{
tm = (tm + 1) % 7;
if(i == 1752 && j == 9)
{
if(k == 2) k = 14;
else k++;
}
else k++;
if(k-1 == 1)
{//本月第一天为周六、日、一,则是good
if(tm == 6 || tm == 0 || tm == 1) Good[i][j] = 1;
}
if(k-1 == d)
{//本月最后一天为周五、六、日,则是luck
if(tm == 5 || tm == 6 || tm == 0) Luck[i][j] = 1;
}
}
}
}
}
int main()
{
table();
int t, y1, m1, y2, m2;
scanf("%d", &t);
while(t--)
{
scanf("%d%d%d%d", &y1, &m1, &y2, &m2);
int luck = 0, good = 0;
for(int i = y1; i <= y2; i++)
{
int st = (i == y1) ? m1 : 1;
int en = (i == y2) ? m2 : 12;
for(int j = st; j <= en; j++)
luck += Luck[i][j], good += Good[i][j];
}
printf("%d %d\n", luck, good);
}
return 0;
}