POJ 2348 Euclid's Game(辗转相除博弈+自由度分析)

题目链接:http://poj.org/problem?id=2348

题目大意:给你两个数a,b,Stan和Ollie轮流操作,每次可以将较大的数减去较小的数的整数倍,相减后结果不能小于0,谁先将其中一个数字变成0谁就获胜。

解题思路:看了挑战程序设计上的,这里我们先假设a<b,当b是a的整数倍是必胜态。我们讨论以下b不是a的整数倍,此时a,b的关系按照自由度的观点(第一次听说),可以分为以下两种情况:

     ①b-a<a

     ②b-a>a

那么对于①,玩家只有从b中减去a这一个选择。如果b-a得到的状态是必败态,那当前就是必胜态,反之,就是必败态。例如从(4,7)出发,只有(4,7)->(4,3)->(1,3)这一条路,(4,7)是必胜态。

但是对于②,有从b中减去a,2a或者更高的倍数等多种选择。假设x是使得b-a*x<a,我们考虑一下两种情况:

    1)将b-a*(x-1),得到状态①。

    2)将b-a*x,不能确定是状态①还是②。

并且我们可以发现,b-a*x是b-a*(x-1)唯一能转移到的状态,如果b-a*(x-1)是必胜态,那就执行b-a*(x-1),但如果是必败态呢,那b-a*x是就是必胜态。所以无论如何只要到了状态②就肯定会赢。

所以我们得到了结论:从初始状态开始最先到达自由度的第二种状态或者得到b是a的整数倍的一方必胜。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4
 5 int main(){
 6     int a,b;
 7     while(~scanf("%d%d",&a,&b)&&(a||b)){
 8         int cnt=0;
 9         while(1){
10             cnt++;
11             if(a>b)
12                 swap(a,b);
13             if(b%a==0)
14                 break;
15             if(b-a>a)
16                 break;
17             b-=a;
18         }
19         if(cnt&1)    puts("Stan wins");
20         else    puts("Ollie wins");
21     }
22 }

POJ 2348 Euclid's Game(辗转相除博弈+自由度分析)

时间: 2024-07-30 12:22:15

POJ 2348 Euclid's Game(辗转相除博弈+自由度分析)的相关文章

POJ 2348 Euclid&#39;s Game

Euclid's Game 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

POJ 2348 Euclid&#39;s Game(博弈)

题目地址:POJ 2348 每一步只有如下三种情况:(假设a>=b) 1:a%b==0    这时候自然是必败态. 2:a<2*b  这时候的下一步是别无选择的,只能是变为(a-b,a),由于该步是唯一的,所以必胜态与必败态是交替的. 3:a>2*b  这时候是必胜态.为什么呢?因为此时总可以转移到一个必败态.由于第2情况的时候两种状态是交替的,而这时候由总可以转换成(a,a%b)和(a,a%b+b),而(a,a%b+b)与(a,a%b)又属于第2种情况的相邻的,所以必有一个是必败态.根

POJ 2348 Euclid&#39;s Game 组合游戏

题目大意:有两个人玩游戏,有两堆石子,每次一个人要从其中一堆石子中拿走一些石子,当出现有一对石子变成0的时候这个人就输了,另一个人就赢了.给出初始石子有多少,问谁能赢. 思路:基础的组合游戏的判定问题,这个题没有给数据范围,非常的坑爹,据说需要long long. 第一次做组合游戏的题目,想想还有些小激动呢.昨天听同学讲了讲,我来现学现卖一下: 由于组合游戏的公平性,那么:如果一个状态的子状态会使先手必败,那么当前状态的先手必胜: 如果不存在一个子状态会使先手必败,那么当前状态先手必败. 利用这

POJ - 2348 Euclid&#39;s Game(博弈论入门题)

题目链接:poj.org/problem?id=2348 题意:给出两个数,两个人进行博弈,每个人都采取最优策略. 每个人可以进行操作:两个数中较大数减去较小数的倍数(可以是1,2...X倍),使得其中一个数先为零的获胜. 每次都先把较小值给a,较大值给b.一开始把必胜态给先手的那个人,然后进行判断. 1.b-a<=a  没办法只能一次一次计算,必胜态不断变换,直到其中一个数刚好为0. 2.b-a>a   不管怎样都是必胜态.b - xa <= a如果这个是必败态,那么b - (x-1)

POJ 2348 Euclid&#39;s Game(博弈)题解

题意:有a,b两个数字,两人轮流操作,每次可以选择两个之中较小的数字,然后另一个数字减去选择数字的任意倍数(不能减到负数),直到其中一个为0,不能操作为败 思路:这题用博弈NP思想,必败点和必胜点之间的转化. 我们假设当前状态为(x,y)其中x>=y,那么必有以下任一状态: 1. x < 2 * y:那么这是只能执行一个操作x - y,如果这个操作之后变成必败态,那么当前为必胜态:反之亦然. 2. x >= 2 * y:显然此时有多种选择,假设x = k * y,如果x - (k - 1

POJ 2348 Euclid Game (模拟题)

Euclid's Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7942   Accepted: 3227 Description Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first player, subtracts any positive multiple of the lesser o

【POJ】2348 Euclid&#39;s Game

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

欧几里德(辗转相除发)算法

辗转相除,又名欧几里德算法(Euclidean algorithm)乃求两个正整数之最大公约数的算法. 此处用函数的递归调用编写了一个小程序: int gcd(int a,int b){ if(a%b==0) return b; else return gcd(b,a%b);} 非递归调用则: int gcd(int a,int b){ int temp; while(a%b!=0) { temp=b; b=a%b; a=temp; } return b;} 通常情况下在gcd(a,b)=1的情

codeforces 267A A. Subtractions(辗转相除)

题目链接: codeforces 267A 题目大意: 给出一个数对,(a,b)每次用较大的减较小的,直到出现0为止,问要进行多少次操作. 题目分析: 大的减小的操作,可以利用取模优化过程,也就是辗转相除,商是操作次数,余数是下一段与之前较小的数继续进行操作的数,水题不做赘述. AC代码: #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using n