最浅谈的SG函数
【更新】
Nim游戏的经验:
每次最多取m个——%(m+1)
阶梯nim——奇数位无视,看偶数位互相独立,成一堆一堆的石子
。
。
。
。
既然被征召去汇总算法。。那么挑个简单点的SG函数好了。。
介绍:{
SG函数是解Nim游戏的一个很好的。。。'思路'么?
Nim游戏是博弈论的一个经典模型,指两个人轮流操作,且双方的操作条件一样(如:中国象棋就不是,因为先手只能动黑子,不能动红子),不能操作的人输(大多是这样。。)
。。在这个前提下,一个'当前局面'就可以用某个SG值来表示。
}
简单的性质:
1、构成DAG 每个节点代表游戏的一个状态,其SG值,定义为其后继的SG值中没有出现的最小的自然数。 若一个状态不可再操作(SG的游戏中通常定义为输),那么没有出现的最小自然数就是0。
2、单个游戏博弈:先手必胜要求【
根节点SG为正,先手从根节点出发
每一回合
先手:每次走向任一SG为0的后继
后手:要么输了(即面对无法操作 没有后继的状态),要么就只能再走到一个SG为正的点,又回到之前的情形
】 所以单个游戏的SG值为其初始状态即根节点的SG。
多个游戏一起博弈:先手必胜要求【
每一个游戏当前的SG值 亦或和为正,(初始时“当前”就是每个游戏的根) ,以下将当前亦或和设为x
每一回合
先手:选择一个游戏i,设其当前走到的点u的SG值为SG[u],选择时要求其满足x^SG[u]<SG[u],这样就一定能走到u的一个后继v,SG[v]=SG[u]^x;
这样 x就变成了x^SG[u]^(SG[u]^x)=0;
{
简单说明①:一定存在这样的u。 因为x为所有SG[i]的亦或和,那么必有一个游戏i当前的SG值得二进制最高位1与x的最高位1相同,则其亦或x之后最高位变0,显然变小了。
简单说明②:为什么要求x^SG[u]<SG[u],不可以走向大于的吗? 毕竟u的后继不一定都小于u,所以的确没这个必要。但是通过说明1,已经证明了一定可以找到SG[v]小于SG[u]的v。
而且,并不是所有u都有 SG值比他大的后继,所以为了思考SG问题方便,要求不能走向 比u的SG值大的后继v。
}
后手:由于不能操作的 即输了的局面的SG亦或和为0, 所以只有后手会(终将会) 面临这个局面。(因为,每一步总有某一个游戏的状态 沿着其DAG往下走了一步)
而后手不能操作SG值已经为0的游戏, 只能操作SG值尚为正的游戏,假设这会使游戏i的SG从a变成b, 则x会^=a^b。 而a!=b所以x一定不会依然是0。这样轮到先手又变回原局面
】
tip1 若不能直接想出SG计算(或者说证明)的方法,实际上打表找规律才是正解。
tip2 有很多SG游戏都是分成好多个子问题,将子问题SG亦或起来求总问题SG的。 时刻记得这个性质。
。
。
。
随便挑道题目吧。
BZOJ4035[HAOI2015]数组游戏 ——tip1 和tip2都能适用于这道题;
【题解要写详细真的比做题要nan!!!】
tip1的话。。。。直接暴力dfs求每个状态的SG值,设白格为1,黑格为0,举例 初始数组为01010。肉眼观察发现: 若两个数组的长度相同,则两个数组亦或 得到的新数组 SG值为这两个数组的SG亦或和。
即,在n固定的情况下,SG[x]^SG[y]==SG[x^y] (这里x,y是二进制转成的十进制)
tip2:【
通过tip2的思路来证明tip1找到的规律。
上面这个规律,等价于,一个01数组的SG值,为其中每一个1的SG值亦或和(如:01011的SG==01000、00010、00001的SG亦或和)
也就是每个白子都是一个子问题,把每个白子的局面翻转成黑即为胜。则多个白子合成的局面等于这些子游戏的SG亦或和
当一个子游戏会影响另一个子游戏时由于是亦或的,所以对SG值的影响会抵消。
】
那么。为什么将游戏x^y分成x和y两个子游戏共同进行博弈,SG值依然是正确的?
【
设游戏A 是由x和y构成的子游戏, 游戏B是局面为x^y的单个游戏。
证明 将游戏x^y分成x和y两个子游戏互不干扰的进行博弈,SG值依然是正确的。
相当于要证明游戏A中不管是对x还是对y的操作在游戏B中有着对应的操作,这样 A和B SG值的变化才能始终是一样的
。
。
现在先手对局面x(考虑y和考虑x等价)的这个子游戏进行一次操作 如:010001翻为000101。
考虑其中被翻转的首位置k:
显然位置k原先是1,
若y中k原先是0, 则 在游戏B中,k是1, 显然在B中可以有一样的操作
若y中k原先是1,则 游戏B中k是0,不可翻转,怎么办?实际上,先手不会这么操作,因为后手可以对y做一样的操作,使SG值又变回来。 所以先手会对其他白子操作,后手最终会不得不进行这种操作,这时,由先手对y做一样的操作,保持必胜的局面。 那么很显然 这一部分的操作,对游戏B就不会有任何影响了。
】
那么剩下的问题就是求出每单个白子的SG值了:
首先输入了n,既然确定了n,那么:
用f[i]表示可以翻i个的点的SG值, 即: 0001000000和000010000 这里的1都最多能翻2个位置,那么它们的SG值都记录在f[2]
用g[i]表示位置i的SG值, 即: 0100000000 ,它的SG值记录在g[2]。
f[i]=g[n div i], 但是由于n<=10^9,所以,f,g都只记录到下标sqrt(n),两个拼起来就可以O(1) 求出每个位置的SG值了。
对于每个f[i]或g[i] 怎么求:对商分块,这样复杂度就是 [求f[i]:sqrt(i)] [求g[i]: sqrt(n/i)]。
当然预处理是 O(n^0.5 * n^0.5) 显然两个根号都不会跑满。O(2)下,预处理只要半秒。还是有点慢慢啊。
- #pragma GCC optimize(2)
- #include <bits/stdc++.h>
- using namespace std;
- int N,n,m,k,x,s,f[],g[];
- int get(int w){
- if (w<=N) {if (f[w]!=-) return f[w];} else
- if (g[n/w]!=-) return g[n/w];
- int d[]; for (int i=;i<;++i) d[i]=;
- for (int x=,y,z=;x<=w;x=w/(w/x)+){
- y=get(w/x); d[z^y]=;
- if (!(w/(w/x)-x&)) z^=y;
- }
- for (int i=;i<;++i) if (!d[i]) return i;
- }
- int main(){
- scanf("%d%d",&n,&m);
- N=ceil(sqrt(n));
- memset(f,-,sizeof f); f[]=;
- memset(g,-,sizeof g);
- for (int i=;i<=N;++i) f[i]=get(i);
- for (int i=n/N-;i>;--i) g[i]=get(n/i);
- while (m--){
- scanf("%d",&k); s=;
- for (int i=;i<=k;++i) scanf("%d",&x),s^=get(n/x);
- s?puts("Yes"):puts("No");
- }
- return ;
- }
乌鸦行
最浅谈的SG函数的更多相关文章
- 浅谈 es6 箭头函数, reduce函数介绍
今天来谈一下箭头函数, es6的新特性 首先我们来看下箭头函数长什么样子, let result = (param1, param2) => param1+param2; 上述代码 按照以前书写 ...
- shell浅谈之十函数
转自:http://blog.csdn.net/taiyang1987912/article/details/39583179 一.简介 Linux Shell编 程中也会使用到函数,函数可以把大的命 ...
- 浅谈js回调函数
回调函数原理: 我现在出发,到了通知你”这是一个异步的流程,“我出发”这个过程中(函数执行),“你”可以去做任何事,“到了”(函数执行完毕)“通知你”(回调)进行之后的流程 例子 1.基本方法 ? 1 ...
- 浅谈JSON.stringify 函数与toJosn函数和Json.parse函数
JSON.stringify 函数 (JavaScript) 语法:JSON.stringify(value [, replacer] [, space]) 将 JavaScript 值转换为 Jav ...
- 浅谈JavaScript eval() 函数
用js的人都应该知道eval()函数吧,虽然该函数用的极少,但它却功能强大,那么问题来了,为什么不常用呢?原因很简单,因为eval()函数是动态的执行其中的字符串,里面有可能是脚本,那么这样的话就有可 ...
- 浅谈C++虚函数
很长时间都没写过博客了,主要是还没有养成思考总结的习惯,今天来一发. 我是重度拖延症患者,本来这篇总结应该是早就应该写下来的. 一.虚函数表 C++虚函数的机制想必大家都清楚了.不清楚的同学请参看各种 ...
- 浅谈JavaScript匿名函数与闭包
一. 匿名函数 //普通函数定义: //单独的匿名函数是无法运行的.就算运行了,也无法调用,因为没有名称. 如: function(){ alert('123'); ...
- 浅谈javascript的函数节流
什么是函数节流? 介绍前,先说下背景.在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),这种事件有一个特点,就是用户不必特地捣乱,他在 ...
- 浅谈JavaScript的函数的call以及apply
我爱撸码,撸码使我感到快乐!大家好,我是Counter.今天就来谈谈js函数的call以及apply,具体以代码举例来讲解吧,例如有函数: function func(a, b) { return a ...
随机推荐
- TOJ 4105
题意:有10万个点,10万个询问,没有更新,求L1<=L<=L2,R1<=R<=R2,有多少个, 其实转换一下:就是求一个矩形 (L1,R1) ----(L2,R2) 中有多少 ...
- CODEVS_1033 蚯蚓的游戏问题 网络流 最小费用流 拆点
原题链接:http://codevs.cn/problem/1033/ 题目描述 Description 在一块梯形田地上,一群蚯蚓在做收集食物游戏.蚯蚓们把梯形田地上的食物堆积整理如下: a(1,1 ...
- hadoop学习 的yarn
Yarn的产生 mapReduc1.0 1单点故障 2扩展效率低 3资源利用率高 降低运维成本 方便数据共享 多计算框架支持 MapReduce Spark Storm Yarn的架构图 Yarn模块 ...
- Java抓屏程序代码
原文:http://www.open-open.com/code/view/1422262655200 import java.awt.Dimension; import java.awt.Recta ...
- 如何删除xcode启动主页面项目列表
Open Xcode, leave the splash screen up and choose "File", "Open Recent Projects" ...
- Cocos2d-x游戏《雷电大战》开源啦!要源代码要资源快快来~~
写在前面的话:这是笔者开发的第二个小游戏<雷电大战>,之前就过这个游戏和<赵云要格斗>一样,终于将会开源. 因为自己的一些个人原因. 这个游戏还没有完毕.可是很多网友都过来寻求 ...
- k进制正整数的对k-1取余与按位取余
华电北风吹 天津大学认知计算与应用重点实验室 日期:2015/8/24 先说一下结论 有k进制数abcd,有abcd%(k−1)=(a+b+c+d)%(k−1) 这是由于kn=((k−1)+1)n=∑ ...
- jquery 获取下拉框 某个text='xxx'的option的属性 非选中 如何获得select被选中option的value和text和......
jquery 获取下拉框 某个text='xxx'的option的属性 非选中 5 jquery 获取下拉框 text='1'的 option 的value 属性值 我写的var t= $(" ...
- pdf reference 格式具体说明
1. PDF概要 1.1. 图像模型 PDF能以平台无关.高效率的方式描叙复杂的文字.图形.排版. PDF 用图像模型来实现设备无关. 图像模型同意应用程序以抽象对象描叙文字.图像.图标.而不是通过详 ...
- 在HDInsight中的Hadoop介绍
在HDInsight中的Hadoop介绍 概览 Azure的HDInsight是,部署和规定的Apache™Hadoop®集群在云中,提供用于管理,分析和大数据报告软件框架中的服务. 大数据 数据被描 ...