摘要: /*这是个很有意思的sg游戏问题。 看出每堆石块的数值非常大,不可能计算所有的sg值。那么只能找规律了根据规律直接计算给定的石块个数的sg值。*/#include <cstdio>int T,N;int a,ans;int main(){ scanf("%d",&T); while(T--) { scanf("%d",&N); ans = 0; for(int i=0;i<N;i++) { scanf("%d",&a); if( a%4==0 ) ans^=(a-1); else if( (a 阅读全文
posted @ 2011-06-14 21:53 AC2012 阅读(441) 评论(1) 推荐(0) 编辑
摘要: /*第一个人,可以任意拿,但必须至少拿一个这个题目不同于常规的游戏题目,首先石子的个数非常的巨大,不可能计算必胜态必败态。而且两个游戏着之间有某种操作上的联系,所以这个题目必须另外来找规律首先根据规则石子个数是1的时候,必败。通过枚举前100个石子的必胜必败态,可以搞清楚必败态的规律来。其实必败态满足fibonaci数列。也就是说石子数位1 2 3 5 8 13 21 34 ..这些石子的时候,不论怎么拿,都会失败那么剩下的那些石子个数都是必胜态。这个规律刚好能够满足题目所说的游戏规则。至于这个规律怎么来得暂时我也不是很清楚。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 阅读全文
posted @ 2011-06-14 20:35 AC2012 阅读(253) 评论(0) 推荐(0) 编辑
摘要: /*单个game的游戏,可以使用sg函数计算,也可以使用必胜态,必败态推断。这里我是计算sg值来算的。如果sg值是0则必败,否则必胜*/#include <cstdio>#include <cstring>int sg[5][5][5][5][5][5];bool used[15000];char in[25];int n,A[7];void init(){ memset(sg,-1,sizeof(sg)); for(int i=0;i<=4;i++) for(int j=0;j<=4;j++) for(int k=0;k<=4;k++) for(in 阅读全文
posted @ 2011-06-14 14:29 AC2012 阅读(154) 评论(0) 推荐(0) 编辑
摘要: /*博弈问题,sg游戏。计算sg值。这里每次操作之后,会产生两个子问题。所以异或之后才是这次操作之后的sg值,然后选择一个不在这个sg集合中的最小的自然数。就ok了。easy....*/#include <cstdio>#include <cstring>int sg[55];bool used[55];int N;void init(){ sg[0] = 0; sg[1] = 0; sg[2] = 1; for(int i=3;i<=50;i++) { memset(used,0,sizeof(used)); for(int j=0;j<=i-2;j++) 阅读全文
posted @ 2011-06-14 13:16 AC2012 阅读(165) 评论(0) 推荐(0) 编辑
摘要: /*采用递推的方法稍微快点,速度1.7秒。 一般的必胜态必败态判断题目*/#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;int a,b,c;bool pn[310][310][310];void init2(){ pn[0][0][0] = 0; for(int i=0;i<=300;i++) { for(int j=0;j<=300;j++) { for(int k=0;k<=300;k++) 阅读全文
posted @ 2011-06-14 11:09 AC2012 阅读(107) 评论(0) 推荐(0) 编辑
摘要: /*1AC的感觉还是比较美妙的博弈问题,关键要知道sg函数的本质,根据定义计算出sg函数值,就可以转化为普通的Nim游戏了还算比较简单吧。*/#include <cstdio>#include <cstdlib>#include <vector>#include <cstring>#include <algorithm>using namespace std;int K,S[10010];int M;vector<int> d[110];int N;int sg[10010];bool vis[10010];int ans 阅读全文
posted @ 2011-06-14 00:35 AC2012 阅读(139) 评论(0) 推荐(0) 编辑