[博弈]Euclid's Game

本文详细解析了欧几里得游戏的算法策略,这是一种两人间的数学游戏,通过不断减去两数中小者倍数直至某一方使一数归零来决定胜负。文章提供了辗转相除法的实现思路,并附带了C++代码示例。

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 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.

Examples

Input
34 12
15 24
0 0

Output

Stan wins
Ollie wins

正确解法:

辗转相除法:

给定两个整数 a和b ,两个人轮流从较大的数字中减去较小的数字的整数倍。若其中一个数字变为0,则这个人就赢了。

首先保证 a<b 因为这两个人决策跟 a,b 的位置没有任何关系,有关系的只是他们的大小。

这样就分为两个情况:

1.  b-a<a

2.  b-a>a

若是第一种情况,那就不用写了,直接模拟看最后是谁赢了。

若是第二种情况:两个人都非常聪明,分为两种情况:

把 b 直接减到 比a还小的状况,那就变成了 1.的情况,之后的结果可能是赢,也可能是输。 

把 b 减到 b>a 的情况,那么下一人必须作出 b=b-a 的决策。从而变成 1.的情况。

要不就直接到达情况,要不就多一步到达情况。

那么我们就可以确定这个人刚开始必胜。

1  if(b%a==0)  break;
2             if(b-a>a)   break;
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<map>
 6 #include<set>
 7 #include<vector>
 8 #include<queue>
 9 #include<algorithm>
10 #include<cmath>
11 using namespace std;
12 typedef long long ll;
13 const int inf=0x7fffffff;
14 const int N=1000000+100;
15 const int M=9999999;
16 const ll mod=1000000000+7;
17 
18 int main()
19 {
20     ll a,b;
21     while(scanf("%lld %lld",&a,&b)&&a&&b)
22     {
23         int f=1;
24         while(true)
25         {
26             if(a>b) swap(a,b);
27             if(b%a==0)  break;
28             if(b-a>a)   break;
29             b=b%a;
30             f=!f;
31         }
32         if(f)   cout<<"Stan wins"<<endl;
33         else cout<<"Ollie wins"<<endl;
34 
35     }
36 
37 
38     return 0;
39 }
View Code

 

转载于:https://www.cnblogs.com/Kaike/p/10675853.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值