06 2011 档案
摘要:/*简单的sg游戏*/#include <cstdio>#include <cstring>int T;int N;int A[22],L[22];int sg[22];int dfs(int x,int m){ int& cur = sg[x]; if(cur!=-1)return cur; bool used[22] ={0}; for(int i=1;i<=m;i++) { if(x>=i) used[ dfs(x-i,m) ] = 1; } for(int i=0;;i++) { if(!used[i]) { cur = i;break; }
阅读全文
摘要:/*无环图,树计算 sg值,求出每个节点处得sg值来*/#include <cstdio>#include <vector>using namespace std;int N,M,Q;int sg[1010];vector<int> G[1010];int dfs(int x){ int& cur = sg[x]; if(cur!=-1) return cur; cur = 0; bool used[1010]={0}; for(int t,i=G[x].size()-1;i>=0;i--) { used[ dfs(G[x][i]) ] = 1
阅读全文
摘要:/*指定一个数 nn ~ oo 是必败态n/9 - n-1 必胜n/18 ~ n/9 必败n/(18*9) ~ n/18-1必胜态n/(18*18) ~ n/(18*9) 必败对于这个题目,很明显的需要用到必胜态和必败态来判断。而且n很大,所以不可能用数组求,所以只能找规律对于n及比n大的数是必败态所有能够转到必败态的状态都是必胜态所以n/9 ~ n-1就是必胜态了所有全部到达必胜态的状态是必败态所以n/18 ~ n/9 就是必败态,可以用一个区间来表示。这里需要注意边界,这里我没有考虑*/#include <cstdio>int n,ans;int main(){ while(s
阅读全文
摘要:/*K个石块,L最大取值。问L取什么样的值,可以保证第二个选手赢1 ~ L 必胜L+1 必败L+2 ~ L+L+1 必胜L+L+2 必败L+L+3 必胜 L+L+2+L必胜L+L+L+3 必败4L+45L+5通过找规律发现,必败态的条件是满足 tL+t,所以我们可以对K找因子,找到最小的那个L就可以了*/#include <cstdio>int K,L;#define min(x,y) ((x)<(y)?(x):(y))int main(){ while(scanf("%d",&K)==1) { int ans = 1000000000; for(
阅读全文
摘要:/*一个很有意思的问题。初看好像不好做。在看,可以转化是取石子问题。因为对于任意一堆数a,b。大的可能是小的好几倍,所以从a上取b可以取多个,然后才能转化为以b为大,a%b为小的下一堆。问题可以转化为:若干堆石子,最后一堆只有一个石子,现在要求从左开始取,只有前一堆取完才能取下一堆。谁取到最后一个石子算胜。可以使用必胜态必败态来做。假设石子数量是1 4 5 1从右往左推,1是必胜态,因为轮到自己的时候,可以执行一步操作就到达要求的目标。 5是必胜态,因为我可以只取4个,然后剩下一个给对方,然后就可以转到下一个必胜态。 4是必胜态,因为我可以只取3个,然后剩下的一个对对方,然后就可以转到下一个必
阅读全文
摘要:/*NIM基础题*/#include <cstdio>int N,A[200001],ans;int main(){ while(scanf("%d",&N)==1) { if(!N) break; ans = 0; for(int i=0;i<N;i++) { scanf("%d",A+i); ans ^= A[i]; } if(ans){printf("Yes\n"); for(int i=0;i<N;i++) { if( A[i]>=(ans^A[i]) ) { printf("%
阅读全文
摘要:/*Nim游戏,首先求出sg异或和的值。如果是胜,判断每堆石块通过变化个数能够达到败态。计数就可以了*/#include <cstdio>int N,A[1010],ans;int main(){ while(scanf("%d",&N)==1) { if(!N) break; ans = 0; for(int i=0;i<N;i++) { scanf("%d",&A[i]);ans^=A[i]; } int cnt=0; if(ans) for(int i=0;i<N;i++) { if( A[i]>= (
阅读全文
摘要:/*NIM游戏基础*/#include <cstdio>int N,a,ans;int main(){ while(scanf("%d",&N)==1) { ans = 0; for(int i=0;i<N;i++) { scanf("%d",&a); ans ^= a; } if(ans) printf("Yes\n"); else printf("No\n"); } return 0;}
阅读全文
摘要:/*由于任何两个相邻的棋子只与他们之间的空为有关。这些空位可以看做是石子数,谁取得了最后一个空位(石子)就是赢家,所以是转化为了普通的NIM游戏。*/#include <cstdio>#include <algorithm>using namespace std;int T,N;int d[1010];int main(){ scanf("%d",&T); while(T--) { scanf("%d",&N); for(int i=0;i<N;i++) scanf("%d",d+i);
阅读全文
摘要:/*稍有难度的题目。sg游戏树删边游戏。不过在树的基础上加入了环,这个环是一个特殊的环,每个环和树只有一个公共节点,没有公共边。而且存在重边。所以对于无向图的保存需要注意这里除了记录下每个节点的连接边以外,还要记录每两个节点之间边的个数。然后分析环的特性:没一个环最终都可以化简,奇数环可以化简为一条边,偶数环可以删去,详细可参见论文。*/#include <cstdio>#include <vector>#include <cstring>using namespace std;int N;int M,K;vector<int> G[110];i
阅读全文
摘要:/*树的删边游戏,sg游戏的一种。sg值的计算是这样的。。定理: 叶子节点的sg为0,中间节点的sg值等于所有子节点的sg加1后的异或*/#include <cstdio>#include <vector>using namespace std;int N;vector<int> G[100001];int sg[100001];bool used[100001];int dfs(int x){ int& cur = sg[x]; if(cur!=-1) return cur; cur = 0; used[x] = true; for(int i=G
阅读全文
摘要:/*树的删边游戏,sg游戏的一种。sg值的计算是这样的。。定理: 叶子节点的sg为0,中间节点的sg值等于所有子节点的sg加1后的异或*/#include <cstdio>#include <vector>using namespace std;int N;vector<int> G[50001];int sg[50001];bool used[50001];int dfs(int x){ int& cur = sg[x]; if(cur!=-1) return cur; cur = 0; used[x] = true; for(int i=G[x]
阅读全文
摘要:/*这个题目和那个连续线段的sg游戏很像。也是要连续的取值。但是这样堆会增加。所以则求sg的时候,要考虑各种子情况。没看懂题目,有点纠结啊*/#include <cstdio>#include <cstring>int S[3];int M;int N;int sg[1010];bool used[1010];int dfs(int n){ int& cur = sg[n]; if( cur!=-1 ) return cur; memset(used,0,sizeof(used)); for(int i=0;i<3;i++) { if(n>=S[i]
阅读全文
摘要:/*这是个很有意思的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
阅读全文
摘要:/*第一个人,可以任意拿,但必须至少拿一个这个题目不同于常规的游戏题目,首先石子的个数非常的巨大,不可能计算必胜态必败态。而且两个游戏着之间有某种操作上的联系,所以这个题目必须另外来找规律首先根据规则石子个数是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
阅读全文
摘要:/*单个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
阅读全文
摘要:/*博弈问题,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++)
阅读全文
摘要:/*采用递推的方法稍微快点,速度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++)
阅读全文
摘要:/*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
阅读全文
摘要:/*Anti-SG游戏*/#include <cstdio>int T;int N;int main(){ int ans,k,a; scanf("%d",&T); while(T--) { scanf("%d",&N); ans = 0; k = 0; for(int i=0;i<N;i++) { scanf("%d",&a); ans ^= a; if( a>1 ) k++; } if(k) { if( ans ) printf("1\n"); else prin
阅读全文
摘要:/*有SJ 定理:对于任意的一个 Anti-SG 游戏,如果我们规定当局面中所有单一游戏的 SG 值为 0 时游戏结束,则先手必胜当且仅当以下两个条件满足任意一个:(1)游戏的 SG 函数不为 0,且游戏中某个单一游戏的 SG 函数大于1。(2)游戏的 SG 函数为 0,且游戏中没有单一游戏的 SG 函数大于 1。*/#include <cstdio>int T;int N;int main(){ int a,ans,k; scanf("%d",&T); while(T--) { scanf("%d",&N); k = 0;
阅读全文
摘要:/* 首先给定一个有向图,这个图是原图经过floyd算法求出来的。原图的强连通分量到新图依然是强连通分量,而每个强连通分量都可以用一个环表示。 所以可以先将新图进行缩点,然后形成了一个有向无环图,对其进行floyd的反操作就可以了。*/// include file#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <cctype>#include <ctime>#include <iostream>#inc
阅读全文
摘要:/*限制路径的最短路径问题,而且多次查询。顶点个数不多使用floyd算法。限制路径,要注意排序。*/// include file#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <cctype>#include <ctime>#include <iostream>#include <sstream>#include <fstream>#include <iomanip>
阅读全文
摘要:/*floyd求最小环。在floyd算法的基础上,我们知道第k次循环,就是求i到j经过编号1~k之间顶点的最小距离。所以可以在第k次循环的时候,利用k-1次循环的信息,找到一个最小解。k次循环完成,就找到了全局的最下解*/// include file#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <cctype>#include <ctime>#include <iostream>#include &l
阅读全文
浙公网安备 33010602011771号