2012年2月24日
摘要: HDU_1849 这个题目实际上就是N堆石子的Nim游戏,具体的一些想法可以参考我的另一篇解题报告:http://www.cnblogs.com/staginner/archive/2012/02/24/2366089.html。#include<stdio.h>#include<string.h>int M;void solve(){ int i, j, k; for(i = k = 0; i < M; i ++) { scanf("%d", &j); k ^= j; } printf("%s\n", k == 0 阅读全文
posted @ 2012-02-24 13:14 Staginner 阅读(274) 评论(0) 推荐(0) 编辑
摘要: HDU_1848 用记忆化搜索的方式处理出sg函数值,然后看sg[n]^sg[m]^sg[p]是否为0即可,推荐一个讲SG函数入门知识的博客:http://www.cnblogs.com/Knuth/archive/2009/09/05/1561007.html。#include<stdio.h>#include<string.h>#define MAXD 1010int f[20], h[MAXD][20], sg[MAXD];void prepare(){ int i; f[0] = f[1] = 1; for(i = 2; i <= 15; i ++) f. 阅读全文
posted @ 2012-02-24 12:41 Staginner 阅读(270) 评论(0) 推荐(0) 编辑
摘要: HDU_1536 比较直观的思路将每一堆的sg函数计算出来,然后看所有的sg函数异或之后是否为0。但实际上我们没必要每一堆都独立计算一遍sg函数,因为游戏规则是一样的,所以sg函数也必然是一样,所以只用开一个一维的sg[]数组记录sg函数的值即可。 此外,一开始调用一下类似dp(10000)的递归函数企图预处理出sg[]的所有值的想法是错误的,因为假定初始石子是10000个的话,有些情况是可能取不到的,比如样例1,假定初始石子是10000个的话对于9999个石子的情况就没法取到。所以一个比较好的方式就是采用记忆化搜索的形式,用哪个就搜哪个。 用于记录后继结点sg函数值的数组最好开成静态的放在递 阅读全文
posted @ 2012-02-24 11:50 Staginner 阅读(325) 评论(0) 推荐(0) 编辑
摘要: HDU_1850 这个相当于有M个子游戏,每个子游戏的SG函数简略写一下之后也比较容易搞出来,最后会发现sg[i][Ni]=Ni,那么如果所有的sg[i][Ni]异或以后的结果为0,是必然会输的。 接着我们考虑先手必赢的情况,如果从一堆中拿走一些石子后,能使得sg异或值为0的话,就算有一种方案,同时根据x^x=0的原理,对于第i个石堆,我们可以先将其余石堆的sg函数的异或值算出来,这样就得到了第i个石堆需要变成多少个石头才能必赢,如果要变成的这个数量比石堆原有的石子数量小的话,就说明存在一种方案。 上面的做法是O(n^2),原因在于我们每次都算了一遍其余sg函数的异或值,但实际上是是没有必.. 阅读全文
posted @ 2012-02-24 09:53 Staginner 阅读(389) 评论(0) 推荐(0) 编辑