一 欧几里德游戏描述:
一开始,板上写有两个不相等的正整数。两个玩家交替写数字,每一次,当前玩家都必须在板上写出任意两个板上数字的差,而且这个数字必须是新的,也就是说,不能与板上任何一个已有的数字相同。当玩家再也写不出新数字时,他就输了。请问,你是选择先行动还是后行动呢?
二 该问题分析过程
注意该题分析时,板上的数字不考虑0和负数。
举例说明:
1)假设一开始板上有的数字为5和7,那么能够写出的序列是2,3,4,1,6(序列是任意的),因此应该是先行动。
观察板上的全部数字是 1,2,3,4,5,6,7;共7个数字
2)假设一开始板上有的数字为3和9,那么能够写出的序列是6(序列是任意的),因此应该是先行动。
观察板上的全部数字是3,6,9 ;共3个数字
3)假设一开始板上有的数字为2和8,那么能够写出的序列是4,6(序列是任意的),因此应该是后行动。
观察板上的全部数字是2,4,6,8 ;共4个数字
4)假设一开始板上有的数字为24和60,那么能够写出的序列是36,12,48(序列是任意的),因此应该是先行动。
观察板上的全部数字是12,24,36,48,60共5个;
观察可得出,板上写出来的数字都是一开始那两个数字m,n的最大公约数 r 的倍数。其实,实质就是与欧几里德算法求最大公约数有关。
欧几里德算法 (求最大公约数),就是我们常说的辗转相除。除法是与减法相对应的运算,所以我们将两个不相等的正整数辗转相减,得到的最小值一定是这两个数的最大公约数。(如果你实在不能理解,就先去弄懂辗转相除求最大公因数的实质)。
因此,由以上分析可得,板上的数字一定都是r 的倍数,且一定小于m,n中较大的数。所以,我们选择 m ,n 中的较大数,然后除以r 就可得出板上的全部数字的个数。若数字为偶数,则后行动;若该数字为奇数,则先行动。
三 实现代码
#include
using namespace std;
#include
int gcd(int m,int n) //求最大公约数
{
int r;
while(n)
{
r=m%n;
m=n;
n=r;
}
return m;
}
int EuclidGame(int m,int n)
{
int r;
if(m<=0||n<=0||m==n) //检测输入 两个不相等的正整数
return -1;
r=gcd(m,n);
if(m>n)
return (m/r)%2;
else
return (n/r)%2;
}
int main()
{
int m,n;
int result;
cout<<"请输入两个不相等的正整数:"<
result=EuclidGame(m,n);
if (result==-1)
cout<<"输入错误!注意:应该输入两个不相等的正整数。"<
cout<<"先行动会赢!"<
cout<<"后行动会赢!"<
四 参考
1 blog.sina.com.cn/s/blog_7496d1d60100t7qe.html
2 Anany Levitin 《算法设计与分析基础》(第2版)