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?还有我没有碰到过这么水的清华大学程序设计竞赛的题目

浙公网安备 33010602011771号