【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

Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 8313 Accepted: 3374

Description

Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be nonnegative. Then Ollie, the second player, does the same with the two resulting numbers, then Stan, etc., alternately, until one player is able to subtract a multiple of the lesser number from the greater to reach 0, and thereby wins. For example, the players may start with (25,7): 
         25 7         11 7          4 7          4 3          1 3          1 0

an Stan wins.

Input

The input consists of a number of lines. Each line contains two positive integers giving the starting two numbers of the game. Stan always starts.

Output

For each line of input, output one line saying either Stan wins or Ollie wins assuming that both of them play perfectly. The last line of input contains two zeroes and should not be processed.

Sample Input

34 1215 240 0

Sample Output

Stan winsOllie wins

Source

Waterloo local 2002.09.28
 

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 )。

解释来源:http://www.cppblog.com/sdz/archive/2010/08/29/125124.html

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.





1 0
原创粉丝点击