zoukankan      html  css  js  c++  java
  • 题解 P1290 【欧几里德的游戏】

    题目链接

    Solution 欧几里得的游戏

    题目大意:有两个数(m,n),你可以将较大的数减去较小的数的正整数倍,先得到(0)的人胜。问给定(m,n)是否有先手必胜方案

    博弈论


    分析:首先可以转化成一个有向图游戏

    我们定义(SG(m,n)),不妨钦定(mgeq n)那么根据题意,显然(SG(m,n)=mex{SG(m-n,n),SG(m-2n,n)dots SG(n,m\%n)})(显然(m\%n < n))

    暴力计算(SG)函数复杂度过高无法承受,我们可以考虑优化,观察式子发现(SG(m-n,n),SG(m-2n,n)dots)如果一直递归下去,会得到(SG(n,m\%n)),因此我们用类似欧几里得算法的方法递归计算(题目名称给提示啊)

    然后注意一点,若(lfloor frac{m}{n} floor > 1),那么(SG(m,n) > 0),考虑证明,如果(lfloor frac{m}{n} floor > 1),那么这个人可以取(nlfloor frac{m}{n} floor)转移到(SG(n,m\%n)),也可以取(n(lfloor frac{m}{n} floor-1))转移到(SG(m \% n + n,n)),让另一个人再取(n),这两种情况奇偶性不同,因此总有一种状态是必败状态,所以当前状态是必胜状态

    另外情况

    (SG(m,0)=0)

    (SG(m,n)=mex(SG(n,m\%n))=!SG(n,m\%n))(如果不是(0)就取(1)的话)

    #include <cstdio>
    using namespace std;
    int t,n,m;
    inline int min(int a,int b){return a < b ? a : b;}
    inline int max(int a,int b){return a > b ? a : b;}
    inline bool solve(int a,int b){
    	if(!b)return false;
    	if(a / b > 1)return true;
    	return !solve(b,a % b);
    }
    int main(){
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d %d",&n,&m);
    		puts(solve(max(n,m),min(n,m)) ? "Stan wins" : "Ollie wins");
    	}
    	return 0;
    }
    
  • 相关阅读:
    iOSIPV6简单测试环境搭建
    SQL存儲過程的調試方法
    Excel的 OleDb 连接串的格式
    RequiredFieldValidator的使用
    GridView導出Excel
    咳嗽對症下藥
    WCF基礎
    WCF配置文件全攻略
    WCF寄宿方式
    WCF綁定
  • 原文地址:https://www.cnblogs.com/colazcy/p/11732325.html
Copyright © 2011-2022 走看看