题意:
给你一个日期,先刚好到2001 11 4算赢,超过的都算输。
走的规则:
1.走到下一天(eg: 1999 1 2 -> 1999 1 3)
2.走到下一个月的同一天(eg:1999 1 2 -> 1999 2 2)
这里要注意了,如果下一个月没有这天的话(1999 10 31 -> 1999 11 31,非法),是不能走的。
思路:
还是一个必赢状态和必输状态的推导:
1.只要此点能到达必输状态,此点就为必赢点。
2.此点只能到达必赢状态,此点就为必输点。
(因为, 你操作过后,留下来的状态是给对手的)
然后就是大模拟:
分别写一个求下一天、下一个月的同一天、前一天的函数。
从后往前推,推导头,返回此点是否是必赢点。
Code:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<map>
#include<cctype>
#include<vector>
#define TEST
#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#ifdef TEST
#define See(a) cout << #a << " = " << a << endl;
#define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
#define debug(a, s, e){ rep(_i, s, e) {cout << a[_i] << ' '; }cout << endl;}
#define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee);}
#else
#define See(a)
#define See2(a, b)
#define debug(a, s, e)
#define debug2(a, s, e, ss, ee)
#endif
const int MAX = 2e9;
const int MIN = -2e9;
const int PI = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int mm[15] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int f[200][15][35];
#define f(i, k, u) f[i - 1898][k][u]
bool isr(int n)
{
if(n % 400 == 0 || n % 4 == 0 && n % 100 != 0)
return true;
return false;
}
void nextDay(int y, int m, int d, int &ty, int &tm, int &td)
{
if(m == 12 && d == 31)
{
ty = y + 1;
tm = 1;
td = 1;
}
else
{
ty = y;
mm[2] = isr(y) ? 29 : 28;
if(d == mm[m])
{
tm = m + 1;
td = 1;
}
else
{
tm = m;
td = d + 1;
}
}
}
bool nextMonth(int y, int m, int d, int &ty, int &tm, int &td)
{
mm[2] = isr(y) ? 29 : 28;
if(m == 12)
{
ty = y + 1;
tm = 1;
td = d;
}
else
{
ty = y;
tm = m + 1;
if(d > mm[tm])
{
return false;
}
td = d;
}
return true;
}
void preDay(int y, int m,int d, int &ty, int &tm, int &td)
{
if(m == 1 && d == 1)
{
ty = y - 1;
tm = 12;
td = 31;
}
else
{
mm[2] = isr(y) ? 29 : 28;
ty = y;
if(d == 1)
{
tm = m - 1;
td = mm[tm];
}
else
{
tm = m;
td = d - 1;
}
}
}
bool getAns(int y, int m, int d, int ey, int em, int ed)
{
while(true)
{
int y1, m1, d1, y2, m2, d2;
nextDay(y, m, d, y1, m1, d1);
bool flag = nextMonth(y, m, d, y2, m2, d2);
if(y == ey & m == em && d == ed)
{
if(flag)
{
return f(y1, m1, d1) == 0 || f(y2, m2, d2) == 0;
}
return f(y1, m1, d1) == 0;
}
else
{
if(flag)
{
f(y, m, d) = f(y1, m1, d1) == 0 || f(y2, m2, d2) == 0;
}
else
{
f(y, m, d) = f(y1, m1, d1) == 0;
}
}
int y3, m3, d3;
preDay(y, m, d, y3, m3, d3);
y = y3;
m = m3;
d = d3;
}
}
int main()
{
int T;
cin >> T;
while(T--)
{
int y, m, d;
scanf("%d%d%d", &y, &m, &d);
Mt(f, -1);
printf("%s\n", getAns(2001, 11, 4, y, m, d) ? "YES" : "NO");
}
return 0;
}