题目:
样例:
翻译:
给出日期(年月日),两个人轮流按照规则操作,首先到达2001年11月4日的人获胜。
规则如下:
1.增加一天
2.增加一个月(到下一个月的当天)
若先手获胜输出YES否则输出NO。
思路:
如果日+1/月+1中有一个为非必胜态,那么当前日期为必胜态;
如果日+1/月+1都是必胜态,那么当前日期为必败态。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
//#define int long long
const int N = 5e3+10;
int mon[20]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
int dp[220][20][40];
bool pan(int x){//判断闰年
x+=1900;
if(x%4==0&&x%100!=0||x%400==0)
return true;
return false;
}
bool cz(int y,int m,int d){//判断当前日期是否在范围内
if(y>2001||y==2001&&m>11||y==2001&&m==11&&d>4)
return false;
if(pan(y)&&m==2&&d==29)return true;
if(mon[m]<d)return false;
return true;
}
int yy,mm,dd;
int dfs(int y,int m,int d){
if(dp[y][m][d]!=-1)return dp[y][m][d];
int flag=1;
//日+1
int y2=0;
if(pan(y)&&m==2)y2=1;//判断闰2月
dd=d+1,mm=m,yy=y;
if(dd>mon[m]+y2){
dd-=mon[m]+y2;mm++;
}
if(mm>12){
mm-=12;yy++;
}
if(cz(yy,mm,dd)) flag&=dfs(yy,mm,dd);//日+1时为必胜态还是必败态
//月+1
yy=y,mm=m+1,dd=d;
if(mm>12){
mm-=12;yy++;
}
if(cz(yy,mm,dd))flag&=dfs(yy,mm,dd);//月+1时为必胜态还是必败态
return dp[y][m][d]=(!flag);//0:必败 1:必胜
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t,n;cin>>t;
memset(dp,-1,sizeof(dp));
dp[101][11][4]=1;
while(t--){
int y,m,d;cin>>y>>m>>d;
if(dfs(y-1900,m,d)){
cout<<"YES"<<endl;
}else cout<<"NO"<<endl;
}
return 0;
}