zoukankan      html  css  js  c++  java
  • POJ 2348 Euclid's Game(辗转相除博弈+自由度分析)

    题目链接:http://poj.org/problem?id=2348

    题目大意:给你两个数a,b,Stan和Ollie轮流操作,每次可以将较大的数减去较小的数的整数倍,相减后结果不能小于0,谁先将其中一个数字变成0谁就获胜。

    解题思路:看了挑战程序设计上的,这里我们先假设a<b,当b是a的整数倍是必胜态。我们讨论以下b不是a的整数倍,此时a,b的关系按照自由度的观点(第一次听说),可以分为以下两种情况:

         ①b-a<a

         ②b-a>a

    那么对于①,玩家只有从b中减去a这一个选择。如果b-a得到的状态是必败态,那当前就是必胜态,反之,就是必败态。例如从(4,7)出发,只有(4,7)->(4,3)->(1,3)这一条路,(4,7)是必胜态。

    但是对于②,有从b中减去a,2a或者更高的倍数等多种选择。假设x是使得b-a*x<a,我们考虑一下两种情况:

        1)将b-a*(x-1),得到状态①。

        2)将b-a*x,不能确定是状态①还是②。

    并且我们可以发现,b-a*x是b-a*(x-1)唯一能转移到的状态,如果b-a*(x-1)是必胜态,那就执行b-a*(x-1),但如果是必败态呢,那b-a*x是就是必胜态。所以无论如何只要到了状态②就肯定会赢。

    所以我们得到了结论:从初始状态开始最先到达自由度的第二种状态或者得到b是a的整数倍的一方必胜。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 
     5 int main(){
     6     int a,b;
     7     while(~scanf("%d%d",&a,&b)&&(a||b)){
     8         int cnt=0;
     9         while(1){
    10             cnt++;
    11             if(a>b) 
    12                 swap(a,b);
    13             if(b%a==0)    
    14                 break;
    15             if(b-a>a) 
    16                 break;
    17             b-=a;    
    18         }
    19         if(cnt&1)    puts("Stan wins");
    20         else    puts("Ollie wins");
    21     }
    22 }
  • 相关阅读:
    frida多版本安装 ubuntu同时安装多个版本的frida
    python爬虫备忘录
    解决linux不能启动google问题
    Centos7 自定义守护进程
    (CentOS 7.0和7.5实验过) 更改网卡名称
    centos 配置网络连接(本机是基于无线网,虚拟机上)
    linux 仿QQ 2.0版本
    linux 实现仿QQ应用程序
    linux 终端、伪终端、虚拟终端的理解
    linux中的make命令
  • 原文地址:https://www.cnblogs.com/fu3638/p/7469787.html
Copyright © 2011-2022 走看看