码迷,mamicode.com
首页 > 其他好文 > 详细

LGOJ1290 欧几里德的游戏

时间:2020-01-31 20:27:32      阅读:72      评论:0      收藏:0      [点我收藏+]

标签:git   mod   理解   不可   游戏   sdi   span   tps   小数   

题目链接

P1290 and UVA10368 (双倍经验【虽然标签差距很有趣】)

题目大意

给定两个数\(n\)\(m\),每次操作可以用较大数减去较小数的正整数倍,不可以减成负数。

先获得一个\(0\)的人获胜,问先手是否必胜。

\(n,m \leq 2^{31}-1\)

多组数据。

Solution

一眼博弈论题吧2333

\(SG\)函数和递归操作应该是摆在眼前的

先记较大数为\(n\),较小数为\(m\)

三种情况:

1.如果当前态的\(n\)\(m\)中有一个已经是\(0\)

显然\(SG(now)=0\),这个人一定输了

2.如果\(n\)已经是\(m\)的倍数

一步操作就可以获胜,\(SG(now)=1\)这个人一定赢了

(上两个都是终止态)

3.\(SG(n,m)=SG(n\space mod \space m,m)\)

这里需要理解一下:

我们假定我们要让这个式子成立

\[SG(n,m) \rightarrow SG(n-k \times m,m)\]

通过控制\(k\)的大小进行博弈,可以使得

\[SG(n \space mod \space m,m)= SG(n,m)\]

得证(其实对于“通过控制\(k\)的大小进行博弈”感性理解一下吧,具体过程不展开了)

CODE

#include <bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm {
inline int read() {
    int res = 0, f = 1;
    char k;
    while (!isdigit(k = getchar()))
        if (k == '-')
            f = -1;
    while (isdigit(k)) res = res * 10 + k - '0', k = getchar();
    return res * f;
}
inline bool work(int n, int m) {
    if (!m)
        return 0;
    if (n/m == 1)
        return !work(m, n % m);
    return 1;
}
signed main() {
    int x,y;
    while (1) {
        x = read();
        y = read();
        if(x==y&&y==0) break; 
        if (work(max(x, y), min(x, y)))
            puts("Stan wins");
        else
            puts("Ollie wins");
    }
    return 0;
}
}  // namespace yspm
signed main() { return yspm::main(); }

(可以发现这段代码是在\(Libre\) \(OJ\)上格式化过的吧2333)

总结

博弈论题要考虑完整情况,对于有些子问题可以先手动博弈一下,就会迎刃而解了

LGOJ1290 欧几里德的游戏

标签:git   mod   理解   不可   游戏   sdi   span   tps   小数   

原文地址:https://www.cnblogs.com/yspm/p/12246573.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!