题目链接: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函数】的更多相关文章

  1. bzoj 1188 [HNOI2007]分裂游戏(SG函数,博弈)

    1188: [HNOI2007]分裂游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 733  Solved: 451[Submit][Status ...

  2. bzoj1188 [HNOI2007]分裂游戏 博弈论 sg函数的应用

    1188: [HNOI2007]分裂游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 973  Solved: 599[Submit][Status ...

  3. bzoj 1188 [HNOI2007]分裂游戏 SG函数 SG定理

    [HNOI2007]分裂游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1394  Solved: 847[Submit][Status][Dis ...

  4. BZOJ 1188: [HNOI2007]分裂游戏(multi-nim)

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1386  Solved: 840[Submit][Status][Discuss] Descripti ...

  5. BZOJ 1188 [HNOI2007]分裂游戏

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1188 学习SG函数的过程中,我先看了一篇叫做 <2008-贾志豪-组合数学略述... ...

  6. bzoj 1188 : [HNOI2007]分裂游戏 sg函数

    题目链接 给n个位置, 每个位置有一个小球. 现在两个人进行操作, 每次操作可以选择一个位置i, 拿走一个小球.然后在位置j, k(i<j<=k)处放置一个小球. 问你先进行什么操作会先手 ...

  7. BZOJ1188:[HNOI2007]分裂游戏(博弈论)

    Description 聪聪和睿睿最近迷上了一款叫做分裂的游戏.该游戏的规则试:共有n个瓶子,标号为0,1,2.....n-1,第i个瓶子中装有p[i]颗巧克力豆,两个人轮流取豆子,每一轮每人选择3个 ...

  8. [2016北京集训试题6]魔法游戏-[博弈论-sg函数]

    Description Solution 首先,每个节点上的权值可以等价于该节点上有(它的权的二进制位数+1)个石子,每次可以拿若干个石子但不能不拿. 然后就发现这和NIM游戏很像,就计算sg函数em ...

  9. BZOJ P1188 HNOI2007 分裂游戏——solution

    题目描述: (<--这个) 组合游戏,——把每个石头看做一个游戏, Multi_game——消去i上的石子后,,k上的游戏又多了一个: 于是就套用multi_game的模型即可 求解SG函数时, ...

随机推荐

  1. Debian自启动知识 2015-03-31 20:23 79人阅读 评论(0) 收藏

    Debian6添加了insserv用来代替update-rc.d.update-rc.d 就不多做介绍. Debian6里边要添加一个自动启动的服务需要先将启动脚本放在/etc/init.d,然后使用 ...

  2. mysql 锁 实验

    CREATE TABLE `kk` ( `a` ) NOT NULL, `b` ) NOT NULL, `c` ) NOT NULL, PRIMARY KEY (`a`), UNIQUE KEY `b ...

  3. IOS-tableViewCell重用机制

    IOS-tableViewCell重用机制 首先介绍tableViewCell原生cell的使用和重用机制 使用dequeueReusableCellWithIdentifier方法,这个方法会从缓存 ...

  4. Java基础知识强化之集合框架笔记40:Set集合之HashSet存储自定义对象并遍历

    1. HashSet存储自定义对象并遍历 2. 代码示例: (1)Student类,如下: package cn.itcast_02; /** * @author Administrator * */ ...

  5. Java——(六)Collection之Queue集合

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- Queue集合 Queue集合用于模拟队列这种数据结构,队列通常是指“先进先出‘(FIFO)的容 ...

  6. windows10UWP:Segoe MDL2 图标指南

    windows10 UWP 开发中,图标的使用非常广泛.为此,微软建议大家使用 Segoe MDL2 Assets 字体来获取图标.Segoe MDL2 Assets 包括了哪里图标,微软在 http ...

  7. HDFS的Java客户端操作代码(查看HDFS下所有的文件存储位置信息)

    1.查看HDFS下所有的文件存储位置信息 package Hdfs; import java.net.URI; import org.apache.hadoop.conf.Configuration; ...

  8. IIS7.5 asp+access数据库连接失败处理 64位系统

    IIS7.5 asp+access数据库连接失败处理(SRV 2008R2 x64/win7 x64) IIS7.5不支持oledb4.0驱动?把IIS运行模式设置成32位就可以了,微软没有支持出64 ...

  9. C#快速排序法

    最近面试的时候,被问到了快速排序法.一时之间,无法想起算法来. 重新看了书本,算法如下: 1)设置两个变量I.J,排序开始的时候:I=0,J=N-1: 2)以第一个数组元素作为关键数据,赋值给key, ...

  10. StringHelper类,内容截取,特别适合资讯展示列表

    public class StringHelper    {        /// <summary>        /// 截字符串        /// </summary> ...