思路:sg函数的使用。
注意点:
1,注意有些状态是不能转移的,而不是转移到失败状态,所以在构建sg函数的时候应该仔细想好限制条件。比如 2001 10 8 ,2001 11 1,这两个都只能一天一天的转移而不能跳一个月,因为不合法。
2,
AC代码:
#include <iostream>
#include <string.h>
#include <cstdio>
using namespace std;
int mem[2002][13][32];
int days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
bool isleap(int y){
if(y%4 == 0 && (y%100 != 0|| y % 400 == 0))return true;
return false;
}
int sg(int y,int m,int d){
if(mem[y][m][d] != -1) return mem[y][m][d];
if(y == 2001 && m == 11 && d == 4) return 0;
int has[10];
memset(has,-1,sizeof(has));
if(isleap(y))days[2] = 29;
else days[2] = 28;
if(d == days[m]){ // 一天天的走
if(m > 11 && y != 2001){
has[sg(y+1,1,1)]++;
}
else{
has[sg(y,m+1,1)]++;
}
}
else{
has[sg(y,m,d+1)]++;
}
if(m == 12){// 跳月
has[sg(y+1,1,d)]++;
}
else{
if(d <= days[m+1] && y < 2001 || y == 2001 && m < 10 || y == 2001 && m == 10 && d < 5){
has[sg(y,m+1,d)]++;
}
}
for(int i = 0;i < 10;i++){
if(has[i] == -1){
return mem[y][m][d] = i;
}
}
return 10000000000000; // 玩笑~
}
int main()
{
int t;
int y,m,d;
memset(mem,-1,sizeof(mem));
cin>>t;
while(t--){
scanf("%d%d%d",&y,&m,&d);
if(sg(y,m,d))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}