【bzoj3567】江南乐
Solution
今天开始啃博弈论了qwq
先mark一篇很棒的博客Portal -->博弈论学习资料
稍微总结一下两个自己容易混淆的点:
1.有一类博弈论问题的主要步骤是首先将原游戏拆分成若干个独立的子游戏,然后原游戏的\(sg\)就是子游戏\(sg\)值的异或和
2.有向图游戏中,对于一个局面,它的\(sg\)是其后继局面的\(sg\)值的\(mex\)
这题的话,首先想怎么拆分
不难发现每一堆的操作其实是独立的,所以我们可以将对一堆石子进行操作看成这个游戏的子游戏
那么问题就变成了要求一堆石子数量为\(x\)的石子堆的\(sg\)值,我们考虑用这堆石子的数量来描述这个局面,那么也就是说我们现在要求\(sg(x)\)
这其实相当于一个有向图游戏
先不考虑时间和空间问题,我们想如何暴力求解\(sg(x)\),一个可行的方法就是记忆化搜索,对于当前局面\(x\),我们枚举一个\(i\)表示将这\(x\)个石子分成的堆数,那么这个后继局面的\(sg\)值就应该是\(sg(a_1)\wedge sg(a_2)\wedge sg(a_3)\wedge...\wedge sg(a_i)\),其中\(a\)表示的是分成\(i\)堆之后每堆的石子数量,然后\(sg(x)\)应该是所有的后继局面的\(sg\)值的\(mex\)
弄清楚这点之后,我们考虑分成\(i\)堆应该怎么分,根据题目要求,显然我们只能分成\(x\%i\)堆石子数量为\(\lfloor \frac{x}{i}\rfloor+1\)的,和\(i-x\%i\)堆石子数量为\(\lfloor \frac{x}{i}\rfloor\)的,那么根据异或的性质不难得出结论分成\(i\)堆的后继局面的\(sg\)值为:
\]
具体的话就是因为如果是偶数那一部分全部异或起来就是\(0\)了
那么现在我们可以写出来一个暴力,考虑如何优化这个东西
注意到里面有一个\(\lfloor \frac{x}{i}\rfloor\),然后这个东西只有\(\sqrt x\)种取值,处理这种东西我们可以用一个分段的套路(莫比乌斯反演既视感qwq),把所有\(\lfloor \frac{x}{i}\rfloor\)相同的\(i\)一起算,接下来在\(\lfloor \frac{x}{i}\rfloor\)相同的前提下,我们再考虑一下奇偶性的问题:会发现如果说\(i\)的奇偶性不变的话,那么\(x%i\)和\(i-x\%i\)的奇偶性也不会发生变化,又因为\(\lfloor \frac{x}{i}\rfloor\)相同,也就是说\(i\)奇偶性不变的话\(sg\)值也不会发生变化
那么所以,我们只要对于每一段\(\lfloor \frac{x}{i}\rfloor\)相同的\(i\),算一下\(i\)的\(sg\)再算一下\(i+1\)的\(sg\),就能够代表这里所有的情况了,总共是\(2\sqrt x\)个数,记忆化搜索一波,问题不大
最后是一些实现上的小细节,如果说求\(mex\)是暴力求的话,我们不能够在递归的时候每次都将判断的数组重置,所以考虑用一个打标记的方式来判,具体就是每次赋成一个不同的\(mark\)值就好了,但是这里有一个问题就是一旦采取这样的方式,在开始统计之后就不能再进行递归操作,所以我们应该在统计之前先递归一遍把这\(2\sqrt x\)个\(sg\)算出来,要注意因为中间可能会递归到自己,所以一开始要先把\(x\)的\(sg\)值赋成\(0\),防止。。一直递归下去qwq
当然啦如果你写的是递推版本就没有那么多麻烦事了qwq
代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100010;
int f[N];
int vis[N];
int n,m,T,F,ans,mark;
int sg(int x){
if (f[x]!=-1) return f[x];
int tmp1,tmp2,tmp=0;
f[x]=0;//stop first
for (int i=2,pos=0;i<=x;i=pos+1){
pos=x/(x/i);
sg(x/i),sg(x/i+1);
}
++mark;
for (int i=2,pos=0;i<=x;i=pos+1){
pos=x/(x/i);
tmp=0;
tmp1=i-x%i;
tmp2=x%i;
if (tmp1&1) tmp^=f[x/i];
if (tmp2&1) tmp^=f[x/i+1];
vis[tmp]=mark;
if (x/(i+1)==x/i){
tmp=0;
tmp1=(i+1)-x%(i+1);
tmp2=x%(i+1);
if (tmp1&1) tmp^=f[x/(i+1)];
if (tmp2&1) tmp^=f[x/(i+1)+1];
vis[tmp]=mark;
}
}
for (int i=0;i<=x;++i)
if (vis[i]!=mark){f[x]=i;return f[x];}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x;
scanf("%d%d",&T,&F);
for (int i=F;i<N;++i) f[i]=-1;
for (int o=1;o<=T;++o){
scanf("%d",&n);
ans=0;
for (int i=1;i<=n;++i){
scanf("%d",&x);
ans^=sg(x);
}
if (ans==0) printf("%d ",0);
else printf("%d ",1);
}
}
【bzoj3567】江南乐的更多相关文章
- BZOJ-3576 江南乐 博弈+优化
fye测试原题,高一全跪,高二学长除了CA爷似乎都A辣(逃) 3576: [Hnoi2014]江南乐 Time Limit: 30 Sec Memory Limit: 512 MB Submit: 1 ...
- bzoj 3576[Hnoi2014]江南乐 sg函数+分块预处理
3576: [Hnoi2014]江南乐 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1929 Solved: 686[Submit][Status ...
- 【BZOJ3576】江南乐(博弈论)
[BZOJ3576]江南乐(博弈论) 题面 BZOJ 洛谷 题解 无论一堆石头怎么拆分,都并不能改变它是一个\(Multi-SG\)的事实. 既然每一组的\(F\)都是固定的,那么我们预处理所有的可能 ...
- 洛谷 P3235 [HNOI2014]江南乐 解题报告
P3235 [HNOI2014]江南乐 Description 两人进行 T 轮游戏,给定参数 F ,每轮给出 N 堆石子,先手和后手轮流选择石子数大于等于 F 的一堆,将其分成任意(大于1)堆,使得 ...
- 【LOJ】#2210. 「HNOI2014」江南乐
LOJ#2210. 「HNOI2014」江南乐 感觉是要推sg函数 发现\(\lfloor \frac{N}{i}\rfloor\)只有\(O(\sqrt{N})\)种取值 考虑把这些取值都拿出来,能 ...
- bzoj3576: [Hnoi2014]江南乐
Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一 ...
- BZOJ 3576 江南乐
http://www.lydsy.com/JudgeOnline/problem.php?id=3576 思路:由于数字巨大,因此N^2异或做法是过不了的,我们考虑将n个石子分成i堆,那么会有n%i堆 ...
- [HNOI 2014]江南乐
Description 题库链接 给你指定一个数 \(f\) ,并给你 \(T\) 组游戏,每组有 \(n\) 堆石子, \(A,B\) 两人轮流对石子进行操作,每次你可以选择其中任意一堆数量不小于 ...
- [HNOI2014]江南乐
Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一 ...
随机推荐
- 用MYSQLworkbench导出数据excel
步骤: 1.先从数据库中将表导出,右键需要导出的表格——>Table Data Export Wizard 2.点击Next,选择你需要把数据存放的文件路径.导出的数据格式(表格的话就默认选择C ...
- HTML5 + CSS3 实现地球绕太阳公转
使用的是正面视角,主要是用 HTML5 + CSS3 来实现,JS只是用来画图. test.html: <!DOCTYPE html> <html> <head> ...
- 使用GitLab创建项目
- Live Archive 训练题
7091 Height Ordering Mrs. Chambers always has her class line up in height order (shortest at the fro ...
- POJ 2063 Investment 滚动数组+完全背包
题目链接: http://poj.org/problem?id=2063 题意: 你现在有现金m元,你要做n年的存款投资,给你k种投资方式,每种需要现金vi元,能获得xi元的理论,一年到期后你要利用拿 ...
- Ubuntu系统升级内核方法
一.查看内核版本 $ uname-sr //查看内核版本 二.去Ubuntu网站http://kernel.ubuntu.com/~kernel-ppa/mainline/下载所需版本的deb文件 w ...
- Microsoft Orleans 之简介
Microsoft Orleans 在.net用简单方法构建高并发.分布式的大型应用程序框架. 原文:http://dotnet.github.io/orleans/ 在线文档:http://dotn ...
- shader language学习(1)——shader language简介背景
shader language,称为着色语言,shade在英语是阴影.颜色深浅的意思.shader language基于物体本身属性和光照条件,计算美格橡塑的颜色值. 实际上这种解释具有明显的时代局限 ...
- WebService(一)
1.简介 Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些应用程序,用 ...
- 敏捷冲刺DAY5
一. 每日会议 1. 照片 2. 昨日完成工作 发布和提供需求功能的实现 用户修改自己的信息 用户界面设计 管理员界面设计 3. 今日完成工作 4. 工作中遇到的困难 1.设置的背景无法显示. 2.一 ...