题意:给定一个日期,然后 A 和 B 双方进行操作,谁先把日期变成2001年11月04日,将获胜,如果超过该日期,则输了,就两种操作。
第一种:变成下一天,比如现在是2001.11.3 变成 2001.11.4
第二种,变成下一个月的同一天,比如现在是2001.10.3 变成 2001.11.3,当然有可能是不成立的,比如2001.1.30 不能变成2001.2.30,因为2月没有30天。
析:因为题目中说了是从1990年到2001年,大约100年的时间,也就是400 * 100,完全可以存储下来,或者是直接暴力并且记忆化,这里就是要处理一些特殊情况,比如闰年,下一天跨年了,或者超过2001.11.4了等等,速度还挺快的。
这第二种解法才是正规的解法,要发现这两种情况的共同点,首先把月份和日份看成一个整体,或者是求和sum就好,因为 11+4 = 15,15 是奇数,那么如果开始的日期是偶数,就一定能够获胜,除非有一种日期从能偶数只能变成偶数,很遗憾,并没有这种日期,也就是只要日期是偶数就是一定能够获胜,下面有解释,当然前提是这两个人都足够聪明,那么是不是是奇数就不能胜了?答案不一定,下面慢慢分析,把日期分成三大类,
第一类,变成一个月的同一天,那么如果能变化的话,sum的奇偶性会发生变化,也就是奇变偶,偶变奇
第二类,就成下一天,对于这个仔细点会发现,sum不全是会变化,只有几个是特例,这第二类就是sum会变化的,
第三类,我们细分一下哪几个特例,也就是说下一天,sum不一定会发生变化的,首先就是 2 月 这个特殊的月份,先考虑不是闰年,那么 2 月就只有 28 天,2 + 28 是偶数,我们推理过如果 sum 是偶数,那么就一定能获胜,那么如果是闰年呢,那么 2 月有 29 天,那么是一个奇数,它的一天是 3.1,奇偶性变成了变化,所以不用考虑 2 月了,同理可以解决 4.30 虽然下一个日期是 5.1 也是偶数,但是它本身偶数,所以一定能获胜,6.30 也是,但是有两个特例也就满足这第三类的,9.30 和 11.30 这两个 sum 是奇数,但是它的下一天是是奇数,下一个月是偶数,也就是说奇偶性不一定不发生变化。但是这两个日期一定能获胜,为什么呢,因为当某个玩家到了 9.30 或者是 11.30 ,我们前面考虑过了如果日期是偶数,就能够获胜,所以它肯定是选择变成下一个日期,这样的话,对方就是奇数了,而下次我就是成偶数了。也就是说如果经过 9.30 或者是 11.30 那么奇偶就会发生翻转。那么这和我们前面说的偶数就一定能够获胜好像是矛盾啊,其实不然,因为每个人都是足够聪明的,能够获胜的那个玩家肯定要避免对方能够拿到这个日期,而且完全可以做到举个例子, 9.30 能够到达 9.30 的只有 9.29 或者是 8.30,那么只要 9.29 的变成下一个月,8.30 的变成下一天,就能够避免对方得到这两个日期,也就能够获胜了。同时如果给定一开始给定的就是 9.30 或 11.30 ,那么这个和虽然不是偶数,也是也能获胜,至少为什么,前面已经说了,经过这两个日期,聪明的玩家的可以把奇偶性翻转,并且以后可以避免让对方再得到这两个日期。
综上,如果先手想胜的话,只有二种情况,一种是日份和月份的和是偶数,第二种,就是开始日期就是 9.30 或者是 11.30。
两种不同的解法,代码差的可不是一点,但是思维量也不是同等的
代码如下:
首先先贴上 dfs 记忆化解决 SG 函数的代码
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <algorithm> #include <vector> #include <map> #include <cctype> #include <cmath> #include <stack> #include <sstream> #include <list> #include <assert.h> #include <bitset> #include <numeric> #define debug() puts("++++") #define gcd(a, b) __gcd(a, b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a, b, sizeof a) #define sz size() #define pu push_up #define pd push_down #define cl clear() #define lowbit(x) -x&x //#define all 1,n,1 #define FOR(i,x,n) for(int i = (x); i < (n); ++i) #define freopenr freopen("in.in", "r", stdin) #define freopenw freopen("out.out", "w", stdout) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> P; const int INF = 0x3f3f3f3f; const LL LNF = 1e17; const double inf = 1e20; const double PI = acos(-1.0); const double eps = 1e-8; const int maxn = 1000 + 10; const int maxm = 100 + 2; const LL mod = 100000000; const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1}; const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1}; const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"}; int n, m; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; inline bool is_in(int r, int c) { return r >= 0 && r < n && c >= 0 && c < m; } bool isLeapYear(int x){ if(x % 400 == 0) return true; if(x % 100 == 0) return false; if(x % 4 == 0) return true; return false; } int nextDay(int x){ int d = x % 100; x /= 100; int m = x % 100; x /= 100; int y = x; if(isLeapYear(y) ? monn[m] == d : mon[m] == d){ d = 1; ++m; if(m > 12) m = 1, ++y; return (y * 100 + m) * 100 + d; } return (y * 100 + m) * 100 + d + 1; } int nextMonth(int x){ int d = x % 100; x /= 100; int m = x % 100; x /= 100; int y = x; if(m == 12) return (y * 100 + 101) * 100 + d; if(m == 1 && d == 29) return isLeapYear(y) ? (y * 100 + 2) * 100 + d : 0; if(m == 1 && d > 29) return 0; if(mon[m+1] < d) return 0; return (y * 100 + m + 1) * 100 + d; } map<int, bool> mp; const int last_date = 20011104; bool dfs(int x){ if(mp.count(x)) return mp[x]; bool &ans = mp[x]; if(x == last_date) return ans = false; int next = nextDay(x); if(!dfs(next)) return ans = true; if((next = nextMonth(x)) && next <= last_date && !dfs(next)) return ans = true; return ans = false; } int main(){ int T; cin >> T; int y, d; while(T-- && scanf("%d %d %d", &y, &m, &d) == 3){ n = (y * 100 + m) * 100 + d; if(dfs(n)) puts("YES"); else puts("NO"); } return 0; }
下面是正解的代码
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <algorithm> #include <vector> #include <map> #include <cctype> #include <cmath> #include <stack> #include <sstream> #include <list> #include <assert.h> #include <bitset> #include <numeric> #define debug() puts("++++") #define gcd(a, b) __gcd(a, b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a, b, sizeof a) #define sz size() #define pu push_up #define pd push_down #define cl clear() #define lowbit(x) -x&x //#define all 1,n,1 #define FOR(i,x,n) for(int i = (x); i < (n); ++i) #define freopenr freopen("in.in", "r", stdin) #define freopenw freopen("out.out", "w", stdout) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> P; const int INF = 0x3f3f3f3f; const LL LNF = 1e17; const double inf = 1e20; const double PI = acos(-1.0); const double eps = 1e-8; const int maxn = 1000 + 10; const int maxm = 100 + 2; const LL mod = 100000000; const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1}; const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1}; const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"}; int n, m; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; inline bool is_in(int r, int c) { return r >= 0 && r < n && c >= 0 && c < m; } int main(){ int T; cin >> T; while(T--){ int y, d; scanf("%d %d %d", &y, &m, &d); if((m+d) % 2 == 0 || m == 9 && d == 30 || m == 11 && d == 30) puts("YES"); else puts("NO"); } return 0; }