【POJ 2348】Euclid's Game 【简单博弈】
来源:互联网 发布:μtorrent mac 编辑:程序博客网 时间:2024/05/02 04:49
可以用搜索的姿势写过。
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;long long a,b;bool Judge(int a,int b){if(a < b)swap(a,b);if(!b)return false;int end = a / b;for(int i = end; i >= 1; --i)if(!Judge(a - i * b,b))return true;return false;}int main(){long long x,y;while(scanf("%lld%lld",&x,&y),x + y)printf("%s\n",Judge(x,y) ? "Stan wins":"Ollie wins");}
下面有个题解:
分析:每次令a大于b,
1 如果a-b<b,则只能有一种减的方法,即a=a-b
2. a-b>b,则有多种减的方法,a减去b的倍数后,可能结果小于b,如果小于b,下一步将是固定的走法;如果减去后达到第一种情况,后面也还是固定减法,即此时你可以决定后面的两种减法(必胜和必败),也就是你可以选择到达下面式子的x还是y,既然可以选择输赢,当然是赢。
x(4,7)-y(4,3)-z(1,3)
#include <iostream> #include<cstdio> using namespace std; int main() { int a,b; while(~scanf("%d%d",&a,&b)&&(a!=0||b!=0)) { bool f=true; while(1) { if(a<b) swap(a,b); if(a%b==0) break; if(a-b>b) break; a-=b; f=!f; } if(f) cout<<"Stan wins\n"; else cout<<"Ollie wins\n"; } return 0; }
Update1:
原po主的分析不是很清楚。即第二个,我再补充一下。
a-b>=b,这个时候我们可以转移到 a%b如果a%b是必败态,那么当前必胜,否则(a%b必胜),我们可以转移到a-b,让对手只能转移到a%b的状态,
这时我方必胜,这就是为什么a>=2*b,时,先手可以决定输赢。
同理,递归下去,终止状态是a%b==0;
Update2:
这个题有个数学结论:
黄金比例
如果两个数相等,或者两数之比大于斐 波拉契数列相邻两项之比的极限((sqrt(5)+1)/2),则先手胜,否则后手胜。
var a,b:longint;f:boolean;procedure swap();begin b:=a xor b; a:=a xor b; b:=a xor b;end;begin while true do begin readln(a,b); if (a=0)and(b=0) then halt; if a>b then swap(); if (a=b)or(b/a>=(sqrt(5)+1)/2) then writeln('Stan wins') else writeln('Ollie wins'); end;end.
[POJ2348]Euclid's Game
Description
25 7 11 7 4 7 4 3 1 3 1 0
an Stan wins.
Input
Output
Sample Input
34 1215 240 0
Sample Output
Stan winsOllie wins
Source
SolutionⅠ
黄金比例
如果两个数相等,或者两数之比大于斐 波拉契数列相邻两项之比的极限((sqrt(5)+1)/2),则先手胜,否则后手胜。
var a,b:longint;f:boolean;procedure swap();begin b:=a xor b; a:=a xor b; b:=a xor b;end;begin while true do begin readln(a,b); if (a=0)and(b=0) then halt; if a>b then swap(); if (a=b)or(b/a>=(sqrt(5)+1)/2) then writeln('Stan wins') else writeln('Ollie wins'); end;end.
SolutionⅡ
给定两堆石子,二人轮流取子,要求只能从石子数目较大的那一堆取子,取子的数目只能是另一堆石子数目的倍数.最终使得某一堆数目为零的一方为胜.
首先,容易看出,对于每一个局面,要么是先手必胜,要么是后手必胜,最终结果完全由当前局面完全确定.
另外,可以简单罗列一下先手必胜和必败的几种局面(两堆石子初始数目都大于零):
1,有一堆石子数目为一,先手必胜, 1,4, 1,2.
2,两堆石子数目差一,且两堆石子数目都不为一,先手必败(只能使后手面对必胜的局面),如 3,4 5,6 .
3,如果数目较大的那一堆是数目较小那一堆的2倍加减一,且不是上面两种局面,先手必胜,2,5 3,5 3,7.
可是上面这些信息对于解决这个问题还是有一些困难.
再进一步试算数目较小的石子,可以发现,当两堆数目相差较大时,总是先手必胜.
事实上,进一步探讨可以发现下面的结论:
1,N<2*M-1时,先手别无选择,只能使之变为 N-M,M 局面,(易见)如3,5 5,7 7,4...
2,设两堆石子数目为N,M(N>M>0,且N,M互质),则若N>=2*M-1,且N - M ! =1时,先手必胜.要求M,N互质是因为对于M,N有公因数的情形,可以同时除以其公因数而不影响结果.
简单说明一下上面结论2的由来. N>=2*M-1时,先手可使之变为 N%M,M 或N%M+M,M两种局面之一,其中有且只有一个必败局面。注意到如果N%M,M不是必败局面,那么N%M+M,M就是必败局面,因为面对N%M+M,M这个局面,你别无选择,只能在前一堆中取M个使对方面对必胜局面(结论1 )。
var a,b:int64;f:boolean;procedure swap();begin b:=a xor b; a:=a xor b; b:=a xor b;end;procedure main;begin while 1=1 do begin if a>b then swap(); if (b mod a=0)then break; if (b-a>a) then break; dec(b,a); if f=false then f:=true; if f=true then f:=false; end; if f then writeln('Stan wins') else writeln('Ollie wins');end;begin while true do begin readln(a,b); f:=true; if (a=0)and(b=0) then halt; main; end;end.
- 【POJ 2348】Euclid's Game 【简单博弈】
- POj-2348-Euclid's Game-博弈
- POJ 2348 Euclid's Game(博弈)
- POJ 2348 Euclid's Game【博弈】
- POJ 2348 Euclid's Game (博弈)
- 【POJ 2348 Euclid's Game】 + 博弈
- 【POJ 2348 Euclid's Game】+ 博弈
- POJ 2348 Euclid's Game <博弈>
- POJ 2348 Euclid's Game(博弈)
- pku 2348 Euclid's Game(简单博弈)
- POJ 2348 Euclid's Game (博弈找规律 )
- poj 2348 Euclid's Game (博弈局面分析)
- POJ 2348 Euclid's Game( 总结规律+组合博弈 )
- [简单博弈] hdu 1525 Euclid's Game
- Euclid's Game---博弈
- poj 2348 Euclid's Game
- POJ-2348-Euclid's Game
- poj 2348 Euclid's Game
- 【NOIP提高组】完美标号
- JAVA基础(1)——基本概念
- 基本算法练习五
- Eclipse设置文本格式为UTF-8/eclipse 工程平铺展开方式,如何将代码工程进行分类
- 编程规范_这个星球上最好的C编程风格
- 【POJ 2348】Euclid's Game 【简单博弈】
- Sublime Text 3 快捷键汇总
- Java继承练习
- servlet实现下载文件功能
- 新IDA6.9 for mac可以用啦 开心呀
- 类的作用域、构造函数、静态成员
- 正则表达式语法
- 关于android studio导入github项目build失败
- (九)java多线程之CyclicBarrier