[BZOJ 1188] [HNOI2007] 分裂游戏 【博弈论|SG函数】
题目链接:BZOJ - 1188
题目分析
我们把每一颗石子看做一个单个的游戏,它的 SG 值取决于它的位置。
对于一颗在 i 位置的石子,根据游戏规则,它的后继状态就是枚举符合条件的 j, k。然后后继状态就是 j 与 k 这两个游戏的和。
游戏的和的 SG 值就是几个单一游戏的 SG 值的异或和。
那么还是根据 SG 函数的定义 , 即 SG(u) = mex(SG(v)) ,预处理求出每个位置的 SG 值。一个位置的 SG 值与它后面的位置有关,是取决于它是倒数第几个位置,那么我们预处理求出的 SG[i] 是指倒数第 i 个位置的 SG 值。
还有一个十分重要的性质,我们不需要考虑每个位置上石子的数量,只需要考虑数量的奇偶,因为如果有偶数个石子,那么这个位置的 SG 值会被异或到整个状态的 SG 中共偶数次,就会抵消,相当于没有。
奇数就是相当于偶数 + 1,因此只要异或一次即可。
组合游戏真是有许多神奇的性质Orz。
代码
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath> using namespace std; const int MaxN = 25, N = 21; int T, n, Mark_Index;
int A[MaxN], SG[MaxN], Mark[MaxN * MaxN]; void Prepare_SG() {
Mark_Index = 0;
memset(Mark, 0, sizeof(Mark));
for (int i = 1; i <= N; ++i) {
++Mark_Index;
for (int j = i - 1; j >= 1; --j)
for (int k = j; k >= 1; --k)
Mark[SG[j] ^ SG[k]] = Mark_Index;
for (int j = 0; j <= N * N; ++j) {
if (Mark[j] != Mark_Index) {
SG[i] = j; break;
}
}
}
} int main()
{
scanf("%d", &T);
Prepare_SG();
for (int Case = 1; Case <= T; ++Case) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &A[i]);
int Temp = 0, Tot = 0;
for (int i = 1; i <= n; ++i)
if (A[i] & 1) Temp ^= SG[n - i + 1];
for (int i = 1; i <= n; ++i) {
if (A[i] == 0) continue;
for (int j = i + 1; j <= n; ++j) {
for (int k = j; k <= n; ++k) {
if ((Temp ^ SG[n - i + 1] ^ SG[n - j + 1] ^ SG[n - k + 1]) != 0) continue;
++Tot;
if (Tot == 1) printf("%d %d %d\n", i - 1, j - 1, k - 1);
}
}
}
if (Tot == 0) printf("-1 -1 -1\n");
printf("%d\n", Tot);
}
return 0;
}
[BZOJ 1188] [HNOI2007] 分裂游戏 【博弈论|SG函数】的更多相关文章
- bzoj 1188 [HNOI2007]分裂游戏(SG函数,博弈)
1188: [HNOI2007]分裂游戏 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 733 Solved: 451[Submit][Status ...
- bzoj1188 [HNOI2007]分裂游戏 博弈论 sg函数的应用
1188: [HNOI2007]分裂游戏 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 973 Solved: 599[Submit][Status ...
- bzoj 1188 [HNOI2007]分裂游戏 SG函数 SG定理
[HNOI2007]分裂游戏 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1394 Solved: 847[Submit][Status][Dis ...
- BZOJ 1188: [HNOI2007]分裂游戏(multi-nim)
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1386 Solved: 840[Submit][Status][Discuss] Descripti ...
- BZOJ 1188 [HNOI2007]分裂游戏
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1188 学习SG函数的过程中,我先看了一篇叫做 <2008-贾志豪-组合数学略述... ...
- bzoj 1188 : [HNOI2007]分裂游戏 sg函数
题目链接 给n个位置, 每个位置有一个小球. 现在两个人进行操作, 每次操作可以选择一个位置i, 拿走一个小球.然后在位置j, k(i<j<=k)处放置一个小球. 问你先进行什么操作会先手 ...
- BZOJ1188:[HNOI2007]分裂游戏(博弈论)
Description 聪聪和睿睿最近迷上了一款叫做分裂的游戏.该游戏的规则试:共有n个瓶子,标号为0,1,2.....n-1,第i个瓶子中装有p[i]颗巧克力豆,两个人轮流取豆子,每一轮每人选择3个 ...
- [2016北京集训试题6]魔法游戏-[博弈论-sg函数]
Description Solution 首先,每个节点上的权值可以等价于该节点上有(它的权的二进制位数+1)个石子,每次可以拿若干个石子但不能不拿. 然后就发现这和NIM游戏很像,就计算sg函数em ...
- BZOJ P1188 HNOI2007 分裂游戏——solution
题目描述: (<--这个) 组合游戏,——把每个石头看做一个游戏, Multi_game——消去i上的石子后,,k上的游戏又多了一个: 于是就套用multi_game的模型即可 求解SG函数时, ...
随机推荐
- VS编辑代码的时候,都会自动在资源浏览器里将文件所在项目展开
如何设置VS编辑代码的时候,都会自动在资源浏览器里将文件所在项目展开 工具-选项-项目和解决方案-常规-在解决方案资源管理器中跟踪活动项(C)
- C程序内存管理
C程序的内存管理 熟悉Java语言的肯定知道,Java中内存管理是由虚拟机帮助我们完毕的,在C/C++中可不是这样,程序猿须要自己去分配和回收内存空间.本文记录了C程序可运行文件的存储结构.在内存中的 ...
- 用.class文件创建对象
第一步: 给你一个编译好的class文件以及它的包名,创建一个对象出来. 1)class文件源代码 package com.wsc.classloader; public class Tool{ p ...
- 构造Nginx避免直接使用IP通路Webserver
他看上去非常Nginx构造,似乎忽略了ip直接访问Web问题,从理论上讲,这是不利于SEO优化,因此,我们希望能够避免直接使用IP访问该网站,但域名.详细介绍了如何做到这一点,看看下面的. 在官方文件 ...
- android 57 QQ登录
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&q ...
- freemarker if..else.. 的使用
FreeMarker是一款模板引擎,今天在做Pad端的时候正好用到,用法非常简单: 在xml配置页面的文件中,直接使用 <#if 1=1> //条件成立要显示的内容 </#if> ...
- css 权威指南笔记(二)元素
替换元素 用来替换元素内容的部分并非有文档内容直接表示. img input 非替换元素 其内容由用户代理(通常是一个浏览器)在元素本身生成的框中显示. 块级元素 块级元素生成一个 元素框,(默认)会 ...
- Unity3D 常用事件
这里总结一下U3D常用的一些事件 //按下事件,GetKeyDown //抬起事件,Input.GetKeyUp //长按事件,Input.GetKey //任意键按下事件,Input.anyKeyD ...
- Android studio混淆
看了一篇关于Android studio混淆的文章http://blog.csdn.net/qq_23547831/article/details/51581491,感觉有必要总结一个简单的混淆版本设 ...
- springMVC -- 整合UEditor(富文本编辑器)
工作中需要用到UEditor编辑文本,在与springMVC进行整合时,出现了一些问题,结果导致,在进行图片上传时出现如下提示: 上网查询了很多相关资料,此处简要记录下,防止以后遇到类似问题. 一种方 ...