随笔分类 - 博弈
摘要:题意:每次可以翻动一个、二个或三个硬币。(Mock Turtles游戏)初始编号从0开始。当N==1时,硬币为:正,先手必胜,所以sg[0]=1.当N==2时,硬币为:反正,先手必赢,先手操作后可能为:反反或正反,方案数为2,所以sg[1]=2。当N==3时,硬币为:反反正,先手必赢,先手操作后可能为:反反反、反正反、正反正、正正反,方案数为4,所以sg[2]=4。位置x:01234567891011121314...sg[x]:1247811 13 1416192122252628…看上去sg值为2x或者2x+1。我们称一个非负整数为odious,当且仅当该数的二进制形式的1出现的次数是奇数
阅读全文
摘要:转自:http://blog.sina.com.cn/s/blog_8f06da99010125ol.html翻硬币游戏一般的翻硬币游戏的规则是这样的:N枚硬币排成一排,有的正面朝上,有的反面朝上。我们从左开始对硬币按1到N编号。第一,游戏者根据某些约束翻硬币,但他所翻动的硬币中,最右边那个硬币的必须是从正面翻到反面。例如,只能翻3个硬币的情况,那么第三个硬币必须是从正面翻到反面。如果局面是正正反,那就不能翻硬币了,因为第三个是反的。第二,谁不能翻谁输。有这样的结论:局面的SG值为局面中每个正面朝上的棋子单一存在时的SG值的异或和。即一个有k个硬币朝上,朝上硬币位置分布在的翻硬币游戏中,SG值
阅读全文
摘要:转自:http://blog.sina.com.cn/s/blog_8f06da990101252l.htmlGreen HackenbushHackenbush游戏是通过移除一个有根图的某些边,直到没有与地板的相连的边。地板用虚线来表示,其中移除某一条边的时候,那条边以上所连着的所有边都会移除,就像砍树枝那样,树枝以上的部分也会被移除。在这节中,我们讨论这个游戏的公平版本,每个玩家在他的回合可以删除任意的边。这个版本叫做Green Hackenbush,每条边都是绿色的,下面我们简称GH游戏。这里还有一个不公平版本,叫做Blue-Red Hackenbush,有些边是蓝色,有些边是红色,而玩
阅读全文
摘要:// Time 15ms, Memory 228K#include
#include
using namespace std;
int main()
{ int i,m,k; while(scanf("%d",&m) && m) { int ans=0; for(i=0;i<m;i++) { scanf("%d",&k); ans^=k; } if(ans) printf("Rabbit Win!\n"); else print...
阅读全文
摘要://Time 0ms, Memory 228K#include
#include
#include
using namespace std;
int main()
{ int t,j,n,m,ans; while(scanf("%d%d",&n,&m)!=EOF) { ans=0; for(int i=0;i<n;i++) { scanf("%d%d",&t,&j); m=abs(t-j)-1; ans^=m; } if...
阅读全文
摘要:// Time 0ms, Memory 236K#include
#include
#include
#include
using namespace std;
int fb[16],sg[1001],v[1001];
int mex(int x)
{ if(sg[x]!=-1) return sg[x]; int i; memset(v,0,sizeof(v)); for(i=1;i=0;i++) { sg[x-fb[i]]=mex(x-fb[i]); v[sg[x-fb[i]]]=1; } for(i=...
阅读全文
摘要://Time 0ms, Memory 288K#include
#include
using namespace std;
int mex(int s,int c)
{ int q=sqrt(s*1.0); while(q+q*q>=s) q--; if(q>n && n) { int ans=0; for(i=0;i>s>>c; ans^=mex(s,c); } cout<<"Case "<<t++<<":"<<endl; if(ans) cout<&l
阅读全文
摘要:这题我先建了表来做的。可以进行两个操作:1、把其中一个数变为比它小的数;2、把其中一个数字0及其右边的所以数字删除。两人轮流进行操作,//Time 281ms, Memory 4140#include
#include
#include
using namespace std;
const int maxn=1000000;
int sg[maxn]={0};
int len(int n)
{ if(n/100000) return 6; if(n/10000) return 5; if(n/1000) return 4; if(n/100) return 3;...
阅读全文
摘要:对于本题,若要当前的 player 赢,剩下所走的步数必须是奇数步。所以对于每步的 player 所放弃的选择的步数为偶数步。因此,对于整个 game 来说,所放弃的步数 m 为偶数步,设所走的步数为 k ,则 n*n-1=m+k;即 n 的奇偶性决定了 k 的奇偶性,也就决定了输赢。(如果有误,请提示!!谢了!!!!)代码如下://Time 0ms, Memory 280K
#include
using namespace std;
int main()
{ int n; while(cin>>n && n) { if(n%2) cout<<"
阅读全文
摘要://Time 78ms, Memory 280K#include
using namespace std;
int main()
{ int i,a,b,k; while(cin>>a>>b && (a || b)) { k=0; if(a1) { k++;break; } i=b;b=a%b;a=i;k++; } if(k%2) cout<<"Stan wins"<<endl; else...
阅读全文
摘要:\\Time 31ms, Memory 4312K#include
#include
#include
using namespace std;
int n,p[1010][1010],sg[1010],b[1010];
int mex(int x)
{ if(sg[x]!=-1) return sg[x]; if(b[x]==0) return 0; int i,v[1010]; memset(v,0,sizeof(v)); for(i=0;i<b[x];i++) { sg[p[x][i]]=mex(p[x][i]); ...
阅读全文
摘要://Time 0ms, Memory 280K#include
using namespace std;
int main()
{ int n,t; while(cin>>n) { t=18; while(t=n) cout<<"Stan wins."<<endl; else cout<<"Ollie wins."<<endl; } return 0;
}
阅读全文
摘要://Time 187ms, Memory 808K#include
#include
#include
using namespace std;
int s[101],h,ans[101],k,m,sg[10010];
int mex(int x)
{ if(sg[x]!=-1) return sg[x]; int i,v[101]; memset(v,0,sizeof(v)); for(i=0;i>k && k) { for(int i=0;i>s[i]; } sort(s,s+k); m...
阅读全文
摘要://Time 15ms, Memory 292K#include
using namespace std;
int main()
{ int n,a[101],t; while(cin>>n && n) { t=0; for(int i=0;i>a[i]; t^=a[i]; } if(t) { int cnt=0; for(int i=0;i=0) cnt++;//注意,大于号的优先级要高于异或运算! ...
阅读全文
摘要:这是一道简单的博弈题。刚开始我用建表的方法来做,代码如下://Time 31ms, Memory 15920K
#include
#include
using namespace std;
int a[2001][2001];
int main()
{ int i,j,n,m,t; memset(a,0,sizeof(a)); for(i=0;i>n>>m && (n || m)) { if(a[n-1][m-1]) cout
int main()
{ int n,m; while(scanf("%d%d",&n,&m)==
阅读全文