LuoguP5407 [THUPC2019]历史行程 题解

要优化干什么?这个题目不该直接推日期就行了吗?(满脸疑惑

这道题目的处理方式其实和P1202 【USACO1.1】黑色星期五Friday the Thirteenth很像,只是稍微有一点技巧而已。


一看到这个题目,先看数据范围:\(1913\leqslant y\leqslant2019\),还以为要打表,但是感觉打表太麻烦了,就立即放弃了这个想法。

(P.s. 正如你们所见,这道题目里面其实还真有个打表的题解。怎么打到表的我先不说,但本人建议还是不要打表的好,毕竟打表不是万能的。)

那么就立即想到了类似上面提到的那道题目的做法——暴力推日期。毕竟数据范围只有\(107\)年(包括\(1913\)\(2019\)年),所以不会超时。

这道题目其实我小号博客里也写过题解的,但是为了方便大家还是把推日期的方法讲下吧:

\(Step~1:\)每次开始的时候,天份和星期数各加\(1\)

\(Step~2:\)判断:

\(1)\)如果天份超过那个月的天数,那么天份归\(1\),同时月份加\(1\)

\(2)\)如果月份大于\(12\),那么月份归\(1\),同时年份加\(1\)

\(3)\)单独判断星期数,如果星期数大于\(6\)(本人题解中用数字\(0\)代表星期日,其他一一对应),那么星期数归\(0\)

\(4)\)这个题目里要判断的:如果已经到了输入年份的\(5\)月,那么开始每逢星期日记一次数,记满两次就跳出循环。

此时输出最终的天份就行了。

注意代码实现的时候要判断闰年的情况,以下是本人考虑闰年的函数\(judge\)

bool check(int y) {
	if(!(y % 100)) {
		if(y % 400)	return 0;
		return 1;
	}
	if(y % 4)	return 0;
	return 1;
}

这样判断闰年就行了。

还有月份,建议是弄一个数组\(a\),记录每个月的天数(此处\(2\)月记\(28\)天,只不过每逢闰年\(2\)月就加\(1\)罢了)。

其他按照上面来实现就可以了。

实在还有不懂的可以来看一下下面的代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

//经度娘搜查可知:1913年1月1日 星期三 
//用week=0表示星期天
const int a[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
int y = 1913, y2, m = 1, d = 1, week = 3, mom = 0;

bool check(int y) {
	if(!(y % 100)) {
		if(y % 400)	return 0;
		return 1;
	}
	if(y % 4)	return 0;
	return 1;
}
int main() {
	scanf("%d", &y2);
	while(1) {
		d++, week++;
		if(week > 6)	week = 0;
		if(d > (check(y) ? (m == 2 ? a[m] + 1 : a[m]) : a[m]))
			d = 1, m++;
		if(m > 12)
			y++, m = 1;
//		printf("%d/%d/%d, %d\n", y, m, d, week);
		if(y == y2 && m == 5) {
			if(week == 0)	mom++;
			if(mom == 2)	break;
		}
	}
	printf("%d", d);
	return 0;
}
//防盗水印:UID=112917

不在右上角点个赞再走嘛qwq?还有我没有碰到过这么水的清华大学程序设计竞赛的题目

posted @ 2021-12-23 21:06  Eason_AC  阅读(46)  评论(0)    收藏  举报