【BZOJ 4035】 4035: [HAOI2015]数组游戏 (博弈)

4035: [HAOI2015]数组游戏

Time Limit: 15 Sec  Memory Limit: 32 MB
Submit: 181  Solved: 89

Description

有一个长度为N的数组,甲乙两人在上面进行这样一个游戏:首先,数组上有一些格子是白的,有一些是黑的。然

后两人轮流进行操作。每次操作选择一个白色的格子,假设它的下标为x。接着,选择一个大小在1~n/x之间的整数

k,然后将下标为x、2x、...、kx的格子都进行颜色翻转。不能操作的人输。现在甲(先手)有一些询问。每次他

会给你一个数组的初始状态,你要求出对于这种初始状态他是否有必胜策略。

Input

接下来2*K行,每两行表示一次询问。在这两行中,第一行一个正整数W,表示数组中有多少个格子是白色的,第二

行则有W个1~N之间的正整数,表示白色格子的对应下标。

Output

对于每个询问,若先手必胜输出"Yes",否则输出"No"。答案之间用换行隔开

Sample Input

3

2

2

1 2

2

2 3

Sample Output

Yes

No

【样例解释】

在第一个询问中,甲选择点1,然后将格子1*1和2*1翻过来即可。

第二个询问中,无论甲选择哪个点,都只能翻掉一个格子。乙只需

翻掉另一个格子就行了。

N<=1000000000 , K,W<=100 , 不会有格子在同

一次询问中多次出现。

HINT

Source

鸣谢bhiaibogf提供

【分析】

  

  把每一个白点看成是一个子游戏,最后将SG函数全部异或起来即可,由SG定理可知有:

$SG(i)$ = $mex${$SG[i*1]$^$SG[i*2]$^$...$ ^ $SG[i*k]$},$k=[2,N/i]$。

  这个第一步应该想到的,但是这样子直接暴力不行。

  实际上某一个SG[i]函数的值只和N/i有关,因此有用的状态只有$O(\sqrt n)$个。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 #define Maxn 500010
 9
10 int n,sq,sg[2][Maxn];
11 int w[Maxn],wl;
12 bool vis[Maxn];
13
14 int nxt(int x,int y) {return x==y?y+1:y/(y/(x+1));}
15
16 void init()
17 {
18     memset(vis,0,sizeof(vis));
19     for(int i=1;i<=n;i=nxt(i,n))
20     {
21         wl=0;int now=0;
22         for(int j=2;j<=i;j=nxt(j,i))
23         {
24             int x=i/j;
25             int nw=(x>sq)?sg[1][n/x]:sg[0][x];
26             // if(!((i/x-i/(x+1))&1)) continue;
27             w[++wl]=now^nw;
28             vis[w[wl]]=1;
29             // now^=nw;
30             if((i/x-i/(x+1))&1) now^=nw;
31         }
32         now=1;
33         while(vis[now]) now++;
34         if(i>sq) sg[1][n/i]=now;
35         else sg[0][i]=now;
36         for(int j=1;j<=wl;j++) vis[w[j]]=0;
37     }
38 }
39
40 int main()
41 {
42     scanf("%d",&n);
43     sq=(int)sqrt((double)n);
44     init();
45     int T;
46     scanf("%d",&T);
47     while(T--)
48     {
49         int sm,ans=0;scanf("%d",&sm);
50         while(sm--)
51         {
52             int x;
53             scanf("%d",&x);
54             ans^=(n/x>sq)?sg[1][x]:sg[0][n/x];
55         }
56         if(ans) printf("Yes\n");
57         else printf("No\n");
58     }
59     return 0;
60 }

不会打,膜了一下lych_cys的代码。。

判断&1那里是如果有偶数个相同的,异或起来等于0,就不用异或进去了。

2017-04-11 10:58:52

时间: 2024-11-29 09:17:30

【BZOJ 4035】 4035: [HAOI2015]数组游戏 (博弈)的相关文章

[HAOI2015]数组游戏

https://zybuluo.com/ysner/note/1233363 题面 有一个长度为\(N\)的数组,每个格子颜色为黑或白.两人轮流操作.每次操作选择一个白格,假设它的下标为\(x\).接着,选择一个大小在\(1-n/x\)之间的整数\(k\),然后将下标为\(x\).\(2x\).....\(kx\)的格子都进行颜色翻转.不能操作的人输.问先手是否有必胜策略. \(30pts\ n\leq20\) \(50pts\ n\leq10^6\) \(100pts\ n\leq10^9,w

[HAOI2015] 数组游戏 - 博弈论,SG函数

有一个长度为N的数组,甲乙两人在上面进行这样一个游戏:首先,数组上有一些格子是白的,有一些是黑的.然后两人轮流进行操作.每次操作选择一个白色的格子,假设它的下标为x.接着,选择一个大小在1~n/x之间的整数k,然后将下标为x.2x.....kx的格子都进行颜色翻转.不能操作的人输.现在甲(先手)有一些询问.每次他会给你一个数组的初始状态,你要求出对于这种初始状态他是否有必胜策略. Solution 用暴力 SG 打个表,发现一段一段的 SG 值都是相同的,所以套个整除分块即可 #include

BZOJ 1022 小约翰的游戏 (Anti-Nim游戏)

题解:注意题目中规定取到最后一粒石子的人算输,所以是Anti-Nim游戏,胜负判断为: 先手必胜: 1.所有堆的石子数都为1且游戏的SG值为0: 2.有些堆的石子数大于1且游戏的SG值不为0. #include <cstdio> int main(){ int t,n,s,x,tmp; scanf("%d",&t); while(t--){ scanf("%d",&n); for(s=tmp=0;n--;)scanf("%d&q

HDU 2176 取(m堆)石子游戏 博弈

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3598    Accepted Submission(s): 2151 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取

【BZOJ 1188】 [HNOI2007]分裂游戏

Description 聪聪和睿睿最近迷上了一款叫做分裂的游戏. 该游戏的规则试: 共有 n 个瓶子, 标号为 0,1,2.....n-1, 第 i 个瓶子中装有 p[i]颗巧克力豆,两个人轮流取豆子,每一轮每人选择 3 个瓶子.标号为 i,j,k, 并要保证 i < j , j < = k 且第 i 个瓶子中至少要有 1 颗巧克力豆,随后这个人从第 i 个瓶子中拿走一颗豆 子并在 j,k 中各放入一粒豆子(j 可能等于 k) .如果轮到某人而他无法按规则取豆子,那么他将输 掉比赛.胜利者可以

BZOJ 1854 【Scoi2010】 游戏

Description lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使用一次. 游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害.也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击bo

51NOD 算法马拉松15(脱欧专场) B君的游戏(博弈)

传送门 B君的游戏 wwwwodddd (命题人) 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 B君和L君要玩一个游戏.刚开始有n个正整数 ai . 双方轮流操作.每次操作,选一个正整数x,将其移除,再添加7个数字 x1,x2-x7 .要求对于 xi ,满足 0<= xi < x 且 x&xi=xi 注意0不能被选取,所以这个游戏一定会结束,而谁无法操作谁就失败. B君根据自己的经验,认为先手胜率高一点,所以B君是先手. B君想知道自己是否必胜. Input 第一

【BZOJ 1115】 [POI2009]石子游戏Kam

1115: [POI2009]石子游戏Kam Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 551  Solved: 339 [Submit][Status] Description 有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数.两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏.问先手是否必胜. Input 第一行u表示数据组数.对于每组数据,第一行N表示石子堆数

VijosP1208欧几里德的游戏 博弈

欧几里德的游戏 题目描述 欧 几里德的两个后代Stan和Ollie正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的.给定两个正整数M和N,从Stan开始,从其中较大的一 个数,减去较小的数的正整数倍,当然,得到的数不能小于0.然后是Ollie,对刚才得到的数,和M,N中较小的那个数,再进行同样的操作……直到一个人 得到了0,他就取得了胜利.下面是他们用(25,7)两个数游戏的过程:     Start:25 7     Stan:11 7     Ollie:4 7     Stan:4