题目大意:
日历上博弈,从给定的日期,按照下述规则跳转日期:
1.跳到第二天;
2.调到下个月相同的日期(如果没有就不能跳转)。
刚刚好跳到2001年11月4日的人胜,跳转时不能跳到2001年11月4日以后。
现在A和B轮流跳,问A是否有必胜策略。
思路:
如果不考虑边界情况,每一个对应的日期都有两个直接相连的后继状态,也同时是两个日期直接相连的后继状态。
这样,所有的状态构成一个DAG,我们可以在DAG上进行DP。
一个状态是必败状态当且仅当它的两个前驱状态都是必胜状态。
一个状态是必胜状态当且仅当它的其中一个前驱状态是必败状态。
我们可以先预处理出所有日期所对应的状态,然后回答即可。
另外本题也有找规律的做法,设月份为m,日期为d。
则当m+d为偶数时必胜,当m+d为奇数时必败。
特别地,当m=9或11且d=30时,也为必胜状态。
1 #include<map> 2 #include<cstdio> 3 #include<cctype> 4 inline int getint() { 5 register char ch; 6 while(!isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 struct Date { 12 int y,m,d; 13 bool operator < (const Date &another) const { 14 if(y<another.y) { 15 return true; 16 } else if(y==another.y){ 17 if(m<another.m) { 18 return true; 19 } else if(m==another.m) { 20 if(d<another.d) return true; 21 } 22 } 23 return false; 24 } 25 bool operator <= (const Date &another) const { 26 if(y<another.y) { 27 return true; 28 } else if(y==another.y){ 29 if(m<another.m) { 30 return true; 31 } else if(m==another.m) { 32 if(d<=another.d) return true; 33 } 34 } 35 return false; 36 } 37 bool isleap() const { 38 return (!(y%4)&&(y%100))||!(y%400); 39 } 40 int day() const { 41 if(m==1||m==3||m==5||m==7||m==8||m==10||m==12) return 31; 42 if(m==4||m==6||m==9||m==11) return 30; 43 return isleap()?29:28; 44 } 45 Date decday() const { 46 Date ret=*this; 47 ret.d--; 48 if(!ret.d) { 49 ret.m--; 50 if(!ret.m) { 51 ret.y--; 52 ret.m=12; 53 } 54 ret.d=ret.day(); 55 } 56 return ret; 57 } 58 Date decmonth() const { 59 Date ret=*this; 60 ret.m--; 61 if(!ret.m) { 62 ret.y--; 63 ret.m=12; 64 } 65 if(ret.d>ret.day()) return (Date){1899,12,31}; 66 return ret; 67 } 68 Date incday() const { 69 Date ret=*this; 70 ret.d++; 71 if(ret.d>ret.day()) { 72 ret.m++; 73 if(ret.m==13) { 74 ret.y++; 75 ret.m=1; 76 } 77 ret.d=1; 78 } 79 return ret; 80 } 81 Date incmonth() const { 82 Date ret=*this; 83 ret.m++; 84 if(ret.m==13) { 85 ret.y++; 86 ret.m=1; 87 } 88 if(ret.d>ret.day()) return (Date){2001,11,5}; 89 return ret; 90 } 91 }; 92 const Date begin=(Date){1900,1,1},end=(Date){2001,11,4}; 93 std::map<Date,bool> m; 94 inline void dp() { 95 for(Date d=end;begin<=d;d=d.decday()) { 96 if(d.incday()<=end) { 97 m[d]|=!m[d.incday()]; 98 } 99 if(d.incmonth()<=end) { 100 m[d]|=!m[d.incmonth()]; 101 } 102 } 103 } 104 inline bool query(const int &y,const int &mm,const int &d) { 105 return m[(Date){y,mm,d}]; 106 } 107 int main() { 108 dp(); 109 for(register int n=getint();n;n--) { 110 const int &y=getint(),&m=getint(),&d=getint(); 111 puts(query(y,m,d)?"YES":"NO"); 112 } 113 return 0; 114 }