zoukankan      html  css  js  c++  java
  • 【AT3939】[ARC091D] Strange Nim(博弈论)

    点此看题面

    • (n)堆石子,每堆石子初始有(a_i)个,且附带一个参数(k_i)
    • 每次可以从一堆石子(假设是第(i)堆,当前剩(x_i)个石子)中取出(1simlfloorfrac{x_i}{k_i} floor)个石子,判断谁必胜。
    • (nle200,a_i,k_ile10^9)

    (SG)函数

    根据(Nim)游戏的基本知识我们知道可以分别求出每堆石子的(SG)函数,然后异或在一起就是全局的(SG)函数了。

    一个显然的转移式:

    [SG(x)= exttt{mex}_{i=1}^{lfloorfrac xk floor}SG(x-i) ]

    看起来很诡异,但我们仔细想想便会找到一个性质,就是(x)的前(lfloorfrac xk floor+1)位应该是一个(0sim lfloorfrac xk floor)的排列!

    但如果(x)(k)的倍数时会存在例外,此时它的前(lfloorfrac xk floor)位是一个(0sim lfloorfrac xk floor-1)的排列,因此(SG(x)=lfloorfrac xk floor)

    证明只需归纳即可,应该还是比较容易的。

    那么我们可以列出一个简单的递推式:

    [SG(x)=egin{cases}0&x<k,\lfloorfrac xk floor&k|x,\SG(x-lfloorfrac xk floor-1)&x>k&&k ot|xend{cases} ]

    主要是考虑第三种转移,直接搞复杂度是(O(k))的,如果(k)很大可能会挂。

    但我们发现对于(lfloorfrac xk floor)相等的连续一段其实可以放一起转移,那么就只会转移(O(lfloorfrac ak floor))次。

    二者一结合,复杂度就是(O(sqrt a))的,正确了。

    代码:(O(nsqrt a))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    using namespace std;
    int n;I int SG(CI x,CI k)//求SG函数
    {
    	if(x<k) return 0;if(!(x%k)) return x/k;//x<k和x是k倍数的两种情况
    	RI y=x/k*k,d=x/k+1,t=(x-y)/d;return SG(x-max(t,1)*d,k);//x/k相同的一段一起转移
    }
    int main()
    {
    	RI i,x,k,t=0;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d%d",&x,&k),t^=SG(x,k);//把每堆石子的SG函数异或起来
    	return puts(t?"Takahashi":"Aoki"),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    简单的mvc之一:简单的开始
    从子类化到工厂模式
    js漫谈
    asp.net mvc框架的一些切入点
    js框架漫谈
    基于公司云平台的即时聊天工具PTALK
    基于公司云平台的素材归档系统(一)
    搜索输入框下拉列表热词搜索的实现
    HTML5 localStorage 的使用
    MVC模式下xml文件的解析
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/AT3939.html
Copyright © 2011-2022 走看看