【VIJOS】1208 欧几里德游戏

题意:给定两个数N,M,每次用M,N中的大数减去小数的正整数倍,记为K,然后用M,N中的小数和K继续进行先前的操作,谁先得到K=0谁赢,问先手(Stan)赢还是后手(Ollie)赢?
0N,M2311

分析:
嗯,博弈论和数论的综合题.

假设当前大数为M,小数为N,那么我们可以通过一次操作,得到以下的状态:

第一个数 第二个数
M-N N
M-2N N
M-3N N
…… ……
M-(K-1)N N
M-KN N

其中 MKN<N .

现在让我们来分类讨论:
Ⅰ 假设状态 MKNN 为先手必胜态,那么:

  • M(K1)NN 为先手必负态
    原因:只能到达 MKNN

  • MPNN,0<P<K1 为先手必胜态;
    原因:状态 M(K1)NN 为必负态,当前状态可以到达对手的必负态,所以为必胜态

Ⅱ 假设状态 MKNN 为先手必负态,那么:

  • M(K1)NN 为先手必胜态;
    原因:同上
  • MPNN,0<P<K1 为先手必胜态;
    原因:同上

综上所述,
Ⅰ 如果 MNN ,那么至少存在 K=1K=2 ,说明是必胜态.
Ⅱ 如果 MN<N ,那么只存在 K=1 ,当前的状态就是 NMN 的相反状态.

而且,我们知道终止状态为 i0 ,终止状态为先手必负态.
我们只要知道辗转的次数cnt:
对于cnt为偶数的情况,先手负;
对于cnt为奇数的情况,先手胜;

举个例子:N=25,M=14,下表必胜态记为P,必负态记为Q.
注意:从下往上看……

M N 状态 原因
25 14 P 只能到达 (9,14)
9 14 Q (9,14) 态即 (14,9)
14 9 Q 只能到达 (5,9)
5 9 P (5,9) 态即 (9,5)
9 5 P 只能到达 (4,5)
4 5 Q (4,5) 态即 (5,4)
5 4 Q 只能到达 (1,4)
1 4 P (1,4) 态即 (4,1)
4 1 P 可以到达 (0,1)
3 1 P 可以到达 (0,1)
2 1 P 可以到达 (0,1)
1 1 P 可以到达 (0,1)
0 1 Q 终止状态为必负态

其实我们到 (4,1) 态就可以得到结果,先前辗转的次数 cnt=4 (cnt+1)mod2=1 .
所以对于先走的人,必然是先手必胜,即Stan取得胜利.

头一次如此顺利地解决博弈论问题23333.

代码:

#include 
#include 
using namespace std;

int cas;

inline int read(void)
{
    int s=0; char c=getchar();
    for (;!isdigit(c);c=getchar());
    for (;isdigit(c);c=getchar()) s=s*10+c-'0';
    return s;
}

inline void swap(int &i,int &j)
{
    i^=j^=i^=j;
}

inline int gcd(int i,int j)
{
    int cnt=0;
    if (ifor (;j;)
    {
        if (i-j>=j) return !(cnt&1);
        i-=j,swap(i,j),cnt++;
    }
    return cnt&1;
}

int main(void)
{
    cas=read();
    for (int cc=1;cc<=cas;cc++)
        printf("%s wins\n",gcd(read(),read())?"Stan":"Ollie");
    return 0;
}

你可能感兴趣的:(博弈论,数论)