zoukankan      html  css  js  c++  java
  • [BZOJ 1228] E&D

    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1228

    Solution:

    感觉自己对博弈论的理论一直了解得不够透彻

    一篇讲原理的文章:Sprague-Grundy定理是怎么想出来的

    现在发现其实可以将SG函数的合成看作为Nim游戏,也顺便能证明其异或运算的正确性了

    对于此题,发现每两堆之间明显是独立的,于是只要求出每组的SG值再异或即可

    但直接求解SG复杂度过高,于是采取打表找规律的方式

    0出现条件:i,j均%2=1
    
    
    1出现条件:i,j均%4=1或2
    
    
    2出现条件:i,j均%8=1或2或3或4
     

    得到sg(i,j)=k的必要条件:

    (i-1)%2^(k+1) < 2^k && (j-1)%2^(k+1) < 2^k

    这样便能在O(logS)时间内求出SG函数

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    int t,n,x,y;
    
    int SG()
    {
        ll pro=2;
        for(int i=0;;++i,pro<<=1)
            if(((x-1)&(pro-1))<(pro>>1) && ((y-1)&(pro-1))<(pro>>1)) return i;
    }
    
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);int res=0;
            for(int i=1;i<=n/2;i++)
                scanf("%d%d",&x,&y),res^=SG();
            puts(res?"YES":"NO");
        }
    }

    Review:

    1、求解A%2^k的技巧:

          直接求解 A&(2^k - 1) 即可,大大优化常数

    2、求解SG函数的一般步骤:

    (1) 使用 数组f 将 可改变当前状态的方式 记录下来。(一般SG函数成规律性变化)

    (2) 然后我们使用 另一个数组 将当前状态x 的后继状态标记。

    (3) 最后模拟mex运算,也就是我们在标记值中 搜索 未被标记值 的最小值,将其赋值给SG(x)。

    3、如果求解SG函数复杂度过高,考虑打表找规律的方式

  • 相关阅读:
    == Equals ReferenceEquals 比较
    数据库 数据类型
    C# 判断路径和文件存在
    OpenXml 2.0 读取Excel
    excel2003, 2007最大行列、sheet数
    将List中部分字段转换为DataTable中
    X64位PC上dsoframer兼容性问题
    winform 客户端 HTTP协议与服务端通信以及解决中文乱码
    VIsual Studio 2010 常用快捷键
    Web Pages(单页面模型)
  • 原文地址:https://www.cnblogs.com/newera/p/9095559.html
Copyright © 2011-2022 走看看