Calendar Game
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3097 Accepted Submission(s): 1809
Problem Description
Adam and Eve enter this year’s ACM International Collegiate Programming Contest. Last night, they played the Calendar Game, in celebration of this contest. This game consists of the dates from January 1, 1900 to November 4, 2001, the contest day. The game starts
by randomly choosing a date from this interval. Then, the players, Adam and Eve, make moves in their turn with Adam moving first: Adam, Eve, Adam, Eve, etc. There is only one rule for moves and it is simple: from a current date, a player in his/her turn can
move either to the next calendar date or the same day of the next month. When the next month does not have the same day, the player moves only to the next calendar date. For example, from December 19, 1924, you can move either to December 20, 1924, the next
calendar date, or January 19, 1925, the same day of the next month. From January 31 2001, however, you can move only to February 1, 2001, because February 31, 2001 is invalid.
A player wins the game when he/she exactly reaches the date of November 4, 2001. If a player moves to a date after November 4, 2001, he/she looses the game.
Write a program that decides whether, given an initial date, Adam, the first mover, has a winning strategy.
For this game, you need to identify leap years, where February has 29 days. In the Gregorian calendar, leap years occur in years exactly divisible by four. So, 1993, 1994, and 1995 are not leap years, while 1992 and 1996 are leap years. Additionally, the years
ending with 00 are leap years only if they are divisible by 400. So, 1700, 1800, 1900, 2100, and 2200 are not leap years, while 1600, 2000, and 2400 are leap years.
Input
The input consists of T test cases. The number of test cases (T) is given in the first line of the input. Each test case is written in a line and corresponds to an initial date. The three integers in a line, YYYY MM DD, represent the date of the DD-th day of
MM-th month in the year of YYYY. Remember that initial dates are randomly chosen from the interval between January 1, 1900 and November 4, 2001.
Output
Print exactly one line for each test case. The line should contain the answer "YES" or "NO" to the question of whether Adam has a winning strategy against Eve. Since we have T test cases, your program should output totally T lines of "YES" or "NO".
Sample Input
3 2001 11 3 2001 11 2 2001 10 3
Sample Output
YES NO NO
Source
Asia 2001, Taejon (South Korea)
Recommend
We have carefully selected several similar problems for you: 1517 1404 2147 1524 1729
博弈。
转化成了奇偶博弈
讨论区这个讲解不错:
说一下此题的为什么:
1.把月和日的和看做一个数sum,记为sum= (m + d),其中m为月份,d为日期。
显然sum不是奇数就是偶数,sum一次变化后是奇数还是偶数呢?
sum的变化有三种情况:
(1)m + (d + 1) 即日期加一,且没有超出本月的日期,变化后为奇数。
(2)(m + 1) + d 即月份加一(12月每一天都可到1月的一天),变化后为奇数。
(3)(m + 1) + 1 即日期加一,但是超出本月的日期,变化后暂时不知道是奇数还是偶数。
由上面的(1)(2)(3)知道,如果sum为偶数且(1)或(2)可行,那么sum必然还是偶数。
如果sum只有变化(3)可行,则使得这样的sum成立的m和d只能是如下几个:
(m,d)={(1,31)(3,31)(5,31)(8,31)(10,31)}.
如果sum为偶数且只有变化(3)可行,则使得这样的sum成立的m和d只能是如下几个:
(m,d)={(1,31)(3,31)(5,31)}.为了使 ((m + 1) + 1)=(m + 2) 为奇数,则
m必须为奇数,显然{(1,31)(3,31)(5,31)}的所有m都为奇数,即如果sum为偶数且
只有变化(3)可行时,sum变化后也为奇数。
所以可以得到如下结论:
如果sum为偶数,那么一次变化后总可以使得sum变为奇数。
2.如果sum是奇数,经过一次变化之后是不是可以仍然是奇数呢?
由于sum的三种变化中,(1)(2)使得sum变化之后成为了偶数,所以为了满足让其仍然为奇数,
显然,我们只能寄希望于变化(3).而能进行变化(3)的(m,d)只有如下几个:
(m,d)={(1,31)((2,28)or(2,29)(leap year))(3,31)(4,30)(5,31)
(6,30)(7,31)(8,31)(9,30)(10,31)(11,30)(12,31)}.
由于sum为奇数,那么m和d的组合只能是如下几个:
(m,d)={(2,29)(8,31)(9,30)(10,31)(11,30)(12,31)}.同样为了使 (m + 2) 为奇数,
则m必须为奇数,显然只有{(9,30)(11,30)}的m为奇数,即如果sum为奇数,经过一次变化之
后可以仍然是奇数的(m,d)只有{(9,30)(11,30)}.
3.以上飞了很多的唾沫,显然都是一些铺垫,我们需要和本题来一个完美的对接。
题目中我们的目的是使得 Adam (moving first)赢,目标状态的sum = 15 = (11 + 4),
目标sum为一个奇数,如果初始数据的sum为偶数或者{(9,30)(11,30)},则Adam 总是可以
将一个sum为奇数的(m,d)抛给Eve.那么Eve就永远只有将奇数sum变化成偶数sum的份,
也就是说Eve不可能到达目标状态。反过来如果 Adam 一开始没有得到偶数或者{(9,30)(11,30)}
状态,那么Adam就把偶数的sum抛给了Eve,Eve得到了控制权。Adam自然也不可能到目标状态。
可能有人会想,Adam把奇数的sum抛给了Eve,那么Eve就不知道把奇数的sum继续变成奇数给
Adam吗?
对于这个问题,只要Adam不留余地就可以了,因为(9,30)前一个状态可能是{(8,30)(9,29)}.
而这两个状态是可以绕过(9,30)的,同理也可以绕过(11,30).
所以只要判断是否可以到奇数的状态即可
#include <stdio.h> #include <math.h> #include <vector> #include <queue> #include <string> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; int main() { int t; scanf("%d",&t); while(t--){ int y,m,d; scanf("%d%d%d",&y,&m,&d); if((m+d)%2==0||m==9||m==11&&d==30) printf("YES\n"); else printf("NO\n"); } return 0; }
版权声明:本文为博主原创文章,转载请注明出处。