HDU 1079 Calendar Game(博弈,找规律可解)

来源:互联网 发布:js写出乘法表 编辑:程序博客网 时间:2024/04/30 01:38

题意:

随机给一个日期,两个人轮流计数,可以将月份加一,也可以将日期加一,但是要符合日期的客观规律(即要考虑平年闰年和日期进位下的进位情况),如果是2001年1月31日则日期+1后变成 2001年2月1日,因为2月没有31天故不可以将月份加一。先到达2001.11.4的获胜。规则大概就是这样。


思路:

1、打SG表,一共一百年,也就是36500天,可以直接暴力打出SG表,注意后一天和后一月的特殊情况(比如平年闰年)。比较暴力但是比较好想,写代码的时候下一点功夫就行了。本人比较懒,没有打表计算…

2、找出博弈的规律。

假如现在离终点日期还是比较远的,就是不考虑临近终点时候的情况。 考虑M + D的奇偶性质。加一个日期在不产生进位的情况下奇偶是变化的。在进位的情况下,奇偶变化的天数是2.28、4.30、6.30、9.30、11.30 如果我现在处于优势的状态,那么我肯定不会主动选择在这些点进行日期+1操作。现在再考虑能不能想办法避免让对手也进行+1操作。每一个日期的下一步都有两个选择。则完全可以避免不给对手留下这些点。

所以我们已经证明了,在距离结果比较远的地方主动方完全一直把握主动权。在距离终点比较远的时候只有9 11两个月是奇数月。11.4的日期和是奇数,所以我们猜测当拿到月份和日期的和是偶数的时候还是比较容易取得胜利的。

所以计算开始给出的日期的月份和日期和,再特判 9 和 11的三十号即可AC。


#include <iostream>#include <iomanip>#include <queue>#include <stack>#include <cstdio>#include <cstring>#include <map>using namespace std;int main(){int casen, y, m, d;scanf("%d", &casen);while(casen--){scanf("%d%d%d", &y, &m, &d);if((m == 11 || m == 9) && d == 30){cout << "YES" << endl;continue;}if((m + d) % 2 == 0) cout << "YES" << endl;else cout << "NO" << endl;}return 0;}


0 0
原创粉丝点击