欧几里德游戏

来源:互联网 发布:中国电信cn2网络 编辑:程序博客网 时间:2024/05/01 09:30

一 欧几里德游戏描述

       一开始,板上写有两个不相等的正整数。两个玩家交替写数字,每一次,当前玩家都必须在板上写出任意两个板上数字的差,而且这个数字必须是新的,也就是说,不能与板上任何一个已有的数字相同。当玩家再也写不出新数字时,他就输了。请问,你是选择先行动还是后行动呢?

二 该问题分析过程

     注意该题分析时,板上的数字不考虑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<iostream>
using namespace std;
#include<cmath>
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<<"请输入两个不相等的正整数:"<<endl;
    cin>>m>>n;
    result=EuclidGame(m,n);
    if (result==-1)
        cout<<"输入错误!注意:应该输入两个不相等的正整数。"<<endl;
      else if(result)
        cout<<"先行动会赢!"<<endl;
        else
          cout<<"后行动会赢!"<<endl;
}


四  参考

1   blog.sina.com.cn/s/blog_7496d1d60100t7qe.html

2 Anany Levitin 《算法设计与分析基础》(第2版)

0 0
原创粉丝点击