题意

有nnn堆石子,给定FFF,每次操作可以把一堆石子数不小于FFF的石子平均分配成若干堆(堆数>1>1>1).

平均分配即指分出来的石子数中最大值减最小值不超过111.不能进行操作就算输.询问先手是否有必胜策略.

分析

因为每一推石子实际上是独立的.于是就可以求出每一堆石子的SGSGSG函数后再异或起来.

于是看看怎么求SG(N)SG(N)SG(N).方法是枚举分成的堆数iii.因为最大−-−最小&lt;=1&lt;=1<=1,那么只可能有两种取值.设:

  • 分出来的较小值为rrr, 较大值就是r+1r+1r+1

    分出来的较大值的堆数为kkk, 较小值的堆数就是i−ki-ki−k

那么有 r=N/ir=N/ir=N/i, k=N%ik=N\%ik=N%i. 那么只要把SG(r)SG(r)SG(r)异或(i−k)(i-k)(i−k)次,把SG(r+1)SG(r+1)SG(r+1)异或kkk次.就能得到一个后继状态的SG值SG值SG值.所以把所有的算出来的值取mexmexmex就得到了SG(N)SG(N)SG(N).这里mexmexmex指没有出现过的最小非负整数值.因为异或偶数次相当于没有异或,所以判断一下kkk或者(i−k)(i-k)(i−k)是否为奇数然后异或一次就行了.

但是这样的时间复杂度是O(N2)O(N^2)O(N2)的,所以我们需要优化.

优化方法类似于莫比乌斯反演中所用到的整除分块.我们对于rrr值相等的iii一起处理.假设我们在处理一个区间[i,j][i,j][i,j],满足ri=ri+1=...=rj=rr_i=r_{i+1}=...=r_j=rri​=ri+1​=...=rj​=r.那么从kik_iki​到kjk_jkj​一定是每一次减少rrr,因为相当于在kkk个较大值中选出rrr个,每一个取走111,组成一堆新的石子.

这个时候我们可以发现kik_iki​的奇偶性一定与ki+2k_{i+2}ki+2​相同,且(i−ki)(i-k_i)(i−ki​)的奇偶性也与(i+2−ki+2)(i+2-k_{i+2})(i+2−ki+2​)相同,所以说分成iii堆和分成i+2i+2i+2推石子得到的SGSGSG值是一样的.那么[i+2,j][i+2,j][i+2,j]的值都对mexmexmex没有贡献,所以我们只需要算iii和i+1i+1i+1的值就行了.那么时间复杂度就被降到了O(nn)O(n\sqrt n)O(nn​).

CODE

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
namespace READ {
inline void read(int &num) {
char ch; while((ch=getchar())<'0'||ch>'9');
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
}
}
using namespace READ;
const int MAXN = 100005;
int T, F, SG[MAXN], vis[MAXN];
inline int sg(int N) { //记忆化搜索,预处理是卡着时限过的,而记忆化搜索会快很多
if(~SG[N]) return SG[N];
if(N < F) return SG[N]=0;
int now, r, k;
for(int i = 2, j; i <= N; i = j+1) { //先把要用到的sg求出来,否则vis数组可能会被重复标号出错
j = N/(N/i); //(但貌似这道题不会WA)
r = N/i, k = N%i;
if(k&1) sg(r+1);
if((i-k)&1) sg(r);
if(j > i) {
r = N/(i+1), k = N%(i+1);
if(k&1) sg(r+1);
if(((i+1)-k)&1) sg(r);
}
}
for(int i = 2, j; i <= N; i = j+1) {
j = N/(N/i);
r = N/i, k = N%i;
now = 0;
if(k&1) now ^= SG[r+1];
if((i-k)&1) now ^= SG[r];
vis[now] = N;
if(j > i) { //可能区间长度只有1
r = N/(i+1), k = N%(i+1);
now = 0;
if(k&1) now ^= SG[r+1];
if(((i+1)-k)&1) now ^= SG[r];
vis[now] = N;
}
}
int mex = 0;
for(; vis[mex] == N; ++mex);
return SG[N]=mex;
}
int main () {
memset(SG, -1, sizeof SG);
read(T), read(F);
while(T--) {
int ans = 0, x, n; read(n);
while(n--)
read(x), ans ^= sg(x);
putchar(ans ? '1' : '0');
if(T) putchar(' '); //注意格式
}
}

BZOJ 3576: [Hnoi2014]江南乐 (SG函数)的更多相关文章

  1. bzoj 3576[Hnoi2014]江南乐 sg函数+分块预处理

    3576: [Hnoi2014]江南乐 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1929  Solved: 686[Submit][Status ...

  2. bzoj 3576: [Hnoi2014]江南乐

    Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一个数F ...

  3. bzoj 3576: [Hnoi2014]江南乐【博弈论】

    这个东西卡常--预处理的时候要先把i%j,i/j都用变量表示,还要把%2变成&1-- 首先每一堆都是不相关子游戏,所以对于每一堆求sg即可 考虑暴力枚举石子数i,分割块数j,分解成子问题求xo ...

  4. 【BZOJ】3576: [Hnoi2014]江南乐

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3576 很显然,这是一个multi-nim游戏. 注意:1.一个点的SG值就是一个不等于它的 ...

  5. 洛谷 P3235 [HNOI2014]江南乐 解题报告

    P3235 [HNOI2014]江南乐 Description 两人进行 T 轮游戏,给定参数 F ,每轮给出 N 堆石子,先手和后手轮流选择石子数大于等于 F 的一堆,将其分成任意(大于1)堆,使得 ...

  6. 【bzoj3576】 Hnoi2014—江南乐

    http://www.lydsy.com/JudgeOnline/problem.php?id=3576 (题目链接) 题意 给出一个数$F$,然后$n$堆石子,每次操作可以把一堆不少于$F$的石子分 ...

  7. luogu P3235 [HNOI2014]江南乐

    传送门 这题又是我什么时候做的(挠头) 首先是个和SG函数有关的博弈论,SG=0则先手必败.显然一堆石子就是一个游戏,而若干堆石子的SG值就是每堆SG的异或和,所以算出每堆石子SG就能知道答案 然后怎 ...

  8. BZOJ 1874 取石子游戏 - SG函数

    Description $N$堆石子, $M$种取石子的方式, 最后取石子的人赢, 问先手是否必胜 $A_i <= 1000$,$ B_i <= 10$ Solution 由于数据很小, ...

  9. [HNOI2014]江南乐 博弈论

    题面 题面 题解 首先我们知道一个关于除法的重要性质:对于一个固定的\(i\),表达式\(\frac{i}{m}\)的取值只有根号个. 因此我们考虑如何优化SG函数的求解. 观察到在取值相同的同一段中 ...

随机推荐

  1. 记crt 在windows与linux服务器之间利用ftp进行文件的上传下载

    我们首先来熟悉一些相关的命令以及操作: ls      #展示linux服务器当前工作目录[你连接sftp时所处的目录]下的所有文件以及文件夹 lcd  F:\niki      #绑定你在windo ...

  2. 解决maven项目无法读取src/main/java目录下面的配置文件问题

    我们在用Mybatis去操作底层数据库的时候,需要用到xml配置文件,一般我们是把配置文件和dao放置在同一层目录. 但是在用idea操作maven项目的时候,我们可能会遇到无法读取到dao对应的ma ...

  3. CSV文件导入数据库和导出数据库

    实例一: <?php $filename = 'test'; //导出文件 header("Content-type: application/vnd.ms-excel; charse ...

  4. Django查找数据库objects.filter() 排序order_by Q()与或非 F()属性之间比较 聚合函数的用法

    条件选取QuerySet的时候,filter表示=参数可以写查询条件,exclude表示!=,querySet.distinct() 去重复(除了get返回值都是QuerySet,可以继续调用所有函数 ...

  5. shell习题第20题:统计文件大小

    [题目要求] 加入需要每小时执行一个脚本.功能:当时间是0点和12点时,将/data/log/下的文件全部清空,注意只能清空文件内容而不能删除文件.而其他时间只需要统计一下每个文件的大小,一个文件一行 ...

  6. s5p6818裸机程序的设计:以GPIO为例

    为了调试方便,首先确保对于硬件的控制没有问题. Makefile # Makefile edited by Schips # 2019-06-21 schips@dingtalk.com # 文件类型 ...

  7. git 去除版本控制

    git会进入当前文件目录, 然后执行如下命令: find . -name ".git" | xargs rm -Rf 该项目就会去除git的版本控制了.再修改的话也不会影响git的 ...

  8. Android监听EditText输入字符串,删除指定的字符

    alert_ed = (EditText) a.findViewById(R.id.alert_ed_queue_num); alert_ed.addTextChangedListener(mText ...

  9. Mysql、Navicat Premium 12连接

    1.配置MySQL80的环境 安装好MySQL,为MySQL配置环境变量.MySQL默认安装在C:\Program Files下. 1)新建MYSQL_HOME变量,并配置:C:\Program Fi ...

  10. “org/apache/commons/logging/LogFactory”错误的解决方式

    用spring-framework-4.2.6.RELEASE-dist时,发生了如下的错误: [java] view plain copy Exception in thread "mai ...