博弈论大作战之 PART2
来源:互联网 发布:ubuntu 17.04 cuda 编辑:程序博客网 时间:2024/04/27 15:34
HDU1536 S-Nim
先暴力预处理所有的值得sg值,然后就是一样的。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,m,a,k,s[101],vis[101],sg[nMax];void init(){ sg[0]=0; for(int i=1;i<nMax;i++) { CLR(vis); for(int j=0;j<k;j++) if(i-s[j]>=0) vis[sg[i-s[j]]]=1; for(int j=0;j<101;j++) if(!vis[j]) {sg[i]=j;break;} }}int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif while(~scanf("%d",&k),k){ FOR(i,0,k-1) scanf("%d",&s[i]); init(); scanf("%d",&m); string ans=""; while(m--){ scanf("%d",&n); int SG=0; while(n--){ scanf("%d",&a); SG ^= sg[a]; } if(SG) ans += "W"; else ans += "L"; } printf("%s\n",ans.c_str()); } return 0;}
HDU1729 Stone Game
看状态sg(S,S)=0,so sg(S,C)=? 设D = min{x | x*x+x >= S}; if C>=D means for (S,C) -> (S,C+1),(S,C+2),.....(S,S) so we can find that sg(S,C) = S-C; if(C<D) sg(S,C) = sg(D-1,C);
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,cas=1;int SG(int S,int C){ if(C==0) return 0; int D = floor(sqrt(S+0.5)); while(D+D*D<S) D++; if(C>=D) return S-C; //if(C==D-1) return 0; return SG(D-1,C);}int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif while(scanf("%d",&n),n){ int s,c,sg=0; while(n--) { scanf("%d%d",&s,&c); sg ^= SG(s,c); } printf("Case %d:\n%s\n",cas++,sg?"Yes":"No"); } return 0;}
HDU1730 Northcott Game
Nim游戏的变形,两个棋子之间的位置数相当于一堆nim石子,然后就。。。#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n,m,t,s,sg=0; while(~scanf("%d%d",&n,&m)){ sg = 0; for(int i=0;i<n;i++) { scanf("%d%d",&t,&s); sg ^= ((int)fabs(t-s)-1); } printf("%s\n",sg?"I WIN!":"BAD LUCK!"); } return 0;}
HDU1848 Fibonacci again and again
数据比较小,暴力处理1-1000的所有sg值,然后你懂的,异或神马的~~ 不解释。。。#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int fi[200],vis[101];int sg[nMax];void init(){ int k=0; fi[1]=1,fi[2]=2;k=3; while(1){ fi[k]=fi[k-1]+fi[k-2]; if(fi[k]>1000) break; k++; } sg[0]=0; for(int i=1;i<=1000;i++) { CLR(vis); for(int j=1;j<k;j++) if(i-fi[j]>=0) vis[sg[i-fi[j]]]=1; else break; for(int j=0;j<100;j++) if(!vis[j]) { sg[i]=j;break;} }}int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif init(); int n,m,p; while(scanf("%d%d%d",&n,&m,&p),n||m||p){ printf("%s\n",(sg[n]^sg[m]^sg[p])?"Fibo":"Nacci"); } return 0;}
HDU1849 Rabbit and Grass
裸的Nim游戏。#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,k;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif while(scanf("%d",&n),n){ int sg=0; while(n--) { scanf("%d",&k); sg ^= k; } printf("%s\n",sg?"Rabbit Win!":"Grass Win!"); } return 0;}
HDU1851A Simple Game
每个游戏都是简单的巴什博弈, sg(n) = n%(m+1);然后就是游戏和。判断一下sg就行了。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int t,n,m,l;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif scanf("%d",&t); while(t--){ int sg=0; scanf("%d",&n); while(n--){ scanf("%d%d",&m,&l); sg ^= (m%(l+1)); } printf("%s\n",sg?"No":"Yes"); } return 0;}
HDU1907 John
Nim游戏的变形,吃最后一个的人输。我们假设至少有一堆石子,那么假设当前是通常Nim游戏的必胜态,那么就是他可以取最后一个石子,但是这个人肯定有办法让这个石子被对手取到,但是如果全是1的话,就不是Nim了。
总结就是,如果有大于1的队存在,就是平常的Nim游戏,否则就是奇偶性判断的问题。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int t,n,k;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif scanf("%d",&t); while(t--){ scanf("%d",&n); int sg=0,flag=0; while(n--){ scanf("%d",&k); sg ^= k; if(k>1) flag=1; } if(flag) printf("%s\n",sg?"John":"Brother"); else printf("%s\n",sg==0?"John":"Brother"); } return 0;}
HDU2509 Be the Winner
就是Nim游戏的变形,不过就是取最后一个输。。。请看上一题。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n,k; while(~scanf("%d",&n)){ int SG=0,flag=0; while(n--) { scanf("%d",&k); SG ^= k; if(k>1) flag=1; } if(flag) printf("%s\n",SG?"Yes":"No"); else printf("%s\n",SG==0?"Yes":"No"); } return 0;}
HDU3980 Paint Chain
我们先看一条链的情况,假设长度为n,每次取m个,那么sg(n,m) 就可以递归求解,当然也可以递推求解,as you like。那么一条圈第一步是固定将他变成一条长n-m的链,于是问题就解决了。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,m;int sg[nMax];int ans=0;int dfs(int n,int m){ if(sg[n]!=-1) return sg[n]; if(n<m) return sg[n]=0; if(n==m) return sg[n]=1; int vis[100]; CLR(vis); for(int i=1;i<=n;i++) if(n-i-m+1>=0){ //ans = max(ans,dfs(i-1,m)^dfs(n-m-i+1,m)); vis[dfs(i-1,m)^dfs(n-m-i+1,m)]=1; } else break; for(int j=0;;j++) if(!vis[j]) return sg[n]=j;}int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int t,cas=1; for(scanf("%d",&t);t>0;t--){ scanf("%d%d",&n,&m); printf("Case #%d: ",cas++); if(n<m) printf("abcdxyzk\n"); else { memset(sg,-1,sizeof(sg)); //ans=0; if(dfs(n-m,m)==0) printf("aekdycoin\n"); else printf("abcdxyzk\n"); //cout<<ans<<endl; } } return 0;}
HDU4155 The Game of 31
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int dfs(int cur,int a[7]){ //if(cur>=31) return 0; for(int i=1;i<7;i++) if(a[i] && cur+i<=31){ a[i]--; if(dfs(cur+i,a)==0) { a[i]++; return 1; } a[i]++; } return 0;}int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif char s[130]; int a[7]; while(~scanf("%s",s)){ for(int i=1;i<7;i++) a[i]=4; int cur=0,man=0; while(s[man]){ cur += s[man]-'0'; a[s[man]-'0']--; man++; } if(cur>=31){ printf("%s %s\n",s,man&1?"A":"B"); continue; } //cout<<cur<<endl; int sg=dfs(cur,a); if(man%2) { printf("%s %s\n",s,sg?"B":"A"); }else { printf("%s %s\n",s,sg==0?"B":"A"); } } return 0;}HDU4203 Doubloon Game
找规律就是其PN值是K+1周期出现的。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int S,k;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int t; scanf("%d",&t); while(t--){ scanf("%d%d",&S,&k); //cout<<S<<' '<<k<<endl; S=S%(k+1); if(k&1){ printf("%s\n",S&1?"1":"0"); }else { if(S<k) printf("%s\n",S&1?"1":"0"); else printf("%d\n",k); } } return 0;}
HDU1524 A Chess Game
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int first[nMax],to[nMax],nxt[nMax],e;void addadge(int u,int v){ to[e]=v;nxt[e]=first[u];first[u]=e;e++;}int sg[nMax];int dfs(int u){ if(sg[u]!=-1) return sg[u]; int vis[1001]; CLR(vis); for(int i=first[u];i!=-1;i=nxt[i]) { vis[dfs(to[i])]=1; } for(int j=0;;j++) if(!vis[j]) return sg[u]=j;}int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n,m; while(~scanf("%d",&n)){ memset(first,-1,sizeof(first));e=0; for(int i=0,j,k;i<n;i++) { scanf("%d",&j); while(j--) { scanf("%d",&k); addadge(i,k); } } memset(sg,-1,sizeof(sg)); while(~scanf("%d",&m),m){ int SG=0,k; while(m--){ scanf("%d",&k); SG ^= dfs(k); } printf("%s\n",SG?"WIN":"LOSE"); } } return 0;}
POJ2484 A Funny Game
啥都不说了,n>=3 是必败态。。。#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n; while(scanf("%d",&n),n){ printf("%s\n",n<=2?"Alice":"Bob"); } return 0;}
POJ2975 Nim
nim游戏,问第一步可以做的选择,我们的目标就是转移到sg=0的点。。。#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int k[nMax],cnt,n;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif while(scanf("%d",&n),n){ int sg = 0; FOR(i,1,n) scanf("%d",&k[i]),sg ^= k[i]; cnt = 0; FOR(i,1,n){ sg ^= k[i]; if(k[i]>sg)cnt++; sg ^= k[i]; } printf("%d\n",cnt); } return 0;}
POJ2234 Matches Game
将石头换成火柴的Nim游戏。。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,k,sg;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif while(~scanf("%d",&n)){ sg = 0; while(n--){ scanf("%d",&k); sg ^= k; } printf("%s\n",sg?"Yes":"No"); } return 0;}
POJ2368 Buttons
这道题和Ural1023是一样的,只是poj的速度比较慢一些。。所以直接暴力枚举是过不掉的。
应为k的因数一定在1-sqrt(k)之间。所以枚举这个区间就行了,但是注意因为我们枚举从三开始,所以最后还要特判k%2==0的情况。。被坑了一下下。。
Ural1023
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int k,l;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif while(~scanf("%d",&k)){ if(k<=2) { puts("0"); return 0; } int n=(int)sqrt(1.0*k+0.5); for(l=3;l<=n+1;l++)if(k%l==0){ printf("%d\n",l-1); return 0; } if(k%2==0 && k/2-1>=2) printf("%d\n",k/2-1); else printf("%d\n",k-1); return 0; } return 0;}
POJ1740 A New Stone Game
楼教主男人八题系列。。堆数为奇数的时候必胜。
堆数为偶数且分成两份一样的时候是必败。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int a[nMax];int n;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif while(scanf("%d",&n),n){ CLR(a); for(int i=0,j;i<n;i++){ scanf("%d",&j); a[j]++; } if(n&1) printf("1\n"); else { int ok=0; for(int i=0;i<=100;i++) if(a[i]&1) { ok=1; break; } printf("%d\n",ok); } } return 0;}
HDU3590 PP and QQ
好题目啊,首先是树的删边游戏,游戏的sg值是这样计算的,叶子的sg=0,中间节点的sg等于其子节点的sg+1的异或和。其次这是一个anti-sg游戏,就是相当于nim游戏中不能操作的人嬴。用哪个号称SJ定理。
第一次试着将树什么的写成类,好有赶脚。。。
特别鸣谢aplc27出的题目。。。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 200#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>class tree{public: int first[nMax],to[nMax],nxt[nMax],e,sg[nMax],vis[nMax]; void clear(){memset(first,-1,sizeof(first));e=0;CLR(vis);} void addadge(int ,int ); int dfs(int );};void tree::addadge(int u,int v){ to[e]=v;nxt[e]=first[u];first[u]=e;e++; to[e]=u;nxt[e]=first[v];first[v]=e;e++;}int tree::dfs(int u){ sg[u]=0; vis[u]=1; for(int i=first[u];i!=-1;i=nxt[i])if(!vis[to[i]]){ sg[u] ^= (dfs(to[i])+1); } return sg[u];}tree p;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n,m; while(~scanf("%d",&n)){ int sg=0,flag=0; FOR(i,1,n){ scanf("%d",&m); p.clear(); for(int i=1,u,v;i<m;i++) { scanf("%d%d",&u,&v); p.addadge(u,v); } if(p.dfs(1)>1) flag=1; sg ^= p.sg[1]; } if(flag) printf("%s\n",sg?"PP":"QQ"); else printf("%s\n",sg==0?"PP":"QQ"); } return 0;}
HDU3094 A tree game
树的删边游戏。#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 200010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>class tree{public: int first[nMax],to[nMax],nxt[nMax],e,sg[nMax],vis[nMax]; void clear(){memset(first,-1,sizeof(first));e=0;CLR(vis);} void addadge(int ,int ); int dfs(int );};void tree::addadge(int u,int v){ to[e]=v;nxt[e]=first[u];first[u]=e;e++; to[e]=u;nxt[e]=first[v];first[v]=e;e++;}int tree::dfs(int u){ sg[u]=0; vis[u]=1; for(int i=first[u];i!=-1;i=nxt[i])if(!vis[to[i]]){ sg[u] ^= (dfs(to[i])+1); } return sg[u];}tree p;int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n,m,t; scanf("%d",&t); while(t--){ scanf("%d",&n); int sg=0; p.clear(); for(int i=1,u,v;i<n;i++) { scanf("%d%d",&u,&v); p.addadge(u,v); } printf("%s\n",p.dfs(1)?"Alice":"Bob"); } return 0;}
HUD3197 Game
树的删边游戏。#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 2010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>class tree{public: int first[nMax],to[nMax],nxt[nMax],e,sg[nMax],vis[nMax]; void clear(){memset(first,-1,sizeof(first));e=0;CLR(vis);} void addadge(int ,int ); int dfs(int );};void tree::addadge(int u,int v){ to[e]=v;nxt[e]=first[u];first[u]=e;e++; to[e]=u;nxt[e]=first[v];first[v]=e;e++;}int tree::dfs(int u){ sg[u]=0; vis[u]=1; for(int i=first[u];i!=-1;i=nxt[i])if(!vis[to[i]]){ sg[u] ^= (dfs(to[i])+1); } return sg[u];}tree p;int node[nMax];int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n,m; while(~scanf("%d",&n)){ int sg=0; p.clear();m=0; for(int i=0,v;i<n;i++) { scanf("%d",&v); if(v==-1) node[m++]=i; else p.addadge(i,v); } for(int i=0;i<m;i++)sg ^= p.dfs(node[i]); printf("%s\n",sg?"YES":"NO"); } return 0;}
HUD3595 GG and MM
单个游戏的话就是哪个欧拉函数有关的游戏。现在这个是典型的Every-SG 我们需要求出的就是传说中的step
对于单个游戏,玩家总是希望自己能够获胜的游戏玩的尽量久,而自己必败的游戏尽快输掉。于是诞生了一下的游戏步数step
step(u) = 0 if game is over
step(u) = max(step(v) | u->v and sg[v]=0 ) if sg[u]>0
step(u) = min (step(v) | u->v ans sg[v]!=0) if sg[u]==0
那么Every-SG的先手必胜就是最大的step为奇数,很神奇吧。跟多的详情请参考09年大神贾志鹏的集训队论文。。。
最后鸣谢下出题的alpc95啊。。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int step[nMax][nMax];int dfs(int a,int b){ step[a][b]=0; if(b==0) return 0; int k=a/b,ok=0; if(dfs(b,a%b)==0){ step[a][b] = step[b][a%b]+1; ok=1; } else { if(k==1) step[a][b] = step[b][a%b]+1; else step[a][b] = step[b][a%b]+2,ok=1; } return ok;}int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n,cp; while(~scanf("%d",&n)){ cp = -1; for(int i=0,u,v;i<n;i++) { scanf("%d%d",&u,&v); if(u<v) swap(u,v); dfs(u,v); cp = max(cp,step[u][v]); } printf("%s\n",cp%2==0?"GG":"MM"); } return 0;}
HDU2999 Stone Game, Why are you always there?
平常的nim游戏。。。#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int sg[nMax];int vis[1000];int a[nMax],k,ans;void init(int n){ sg[0]=0;ans=0; for(int i=1;i<=n;i++) { CLR(vis); for(int j=0;j<k;j++) { for(int x=1;x<=i;x++) if(x+a[j]-1<=i){ //ans = max(ans,sg[x-1]^sg[i-(x+a[j]-1)]); vis[sg[x-1]^sg[i-(x+a[j]-1)]]=1; }else break; } for(int j=0;;j++) if(!vis[j]) {sg[i]=j;break;} } //printf("%d\n",ans);}int main(){#ifndef ONLINE_JUDGE// freopen("input.txt","r",stdin);#endif int n,m; while(~scanf("%d",&k)){ FOR(i,0,k-1) scanf("%d",&a[i]); init(1000); scanf("%d",&m); while(m--){ scanf("%d",&ans); printf("%d\n",sg[ans]?1:2); } } return 0;}
- 博弈论大作战之 PART2
- 博弈论大作战之 PART1
- python大作战之排序
- python大作战之集合
- python大作战之生成器
- java之旅之习题大作战
- 家有千金之零花钱大作战
- 省钱大作战之图片色彩
- 电视剧推荐之求婚大作战
- java之核心问题大作战
- python序列大作战之可变序列
- python大作战之迭代器初级篇
- 自考路之C++大作战(上)
- 自考路之C++大作战(中)
- 自考路之C++大作战(下)
- 数字大作战:宽带报障系列之错误633
- 刷题记之代码能力大作战一
- 刷题记之代码能力大作战二
- 嵌入式开发之Qt学习篇——1、Qt5.1.0安装与配置
- vs2005 在windows 7 下调试的配置
- Sequence Sum Possibi
- 数组最大最小方法(二)
- Web设计中的5大经典争议
- 博弈论大作战之 PART2
- excel数据源刷数据时不能排列问题
- Android 蓝牙4.0 BLE调试
- sr收藏资料总结
- <Git>在eclipse中用git clone一个项目编辑报错
- K - Goldbach's Conjecture
- 读书笔记:《游戏之旅——我的编程感悟》
- 机器学习的时代来临,人类应该做点什么?
- distinct语句学习