[SG函数 + 分块] BZOJ4035: [HAOI2015]数组游戏
2017-11-28 19:36
387 查看
博弈好题。这种博弈的01取反的模型可以把白色看做有奇数个石子,黑色看做偶数个,因为同一位置偶数个石子SG值异或会抵消…..
这么理解的话,可以把一个石子,即一个白块看做一个独立的游戏。
现在只需求SG值。
SG(i)=mex{0,SG(2i),SG(2i) ^ SG(3i),SG(2i) ^ SG(3i) ^ SG(4i),...}
一般SG函数的题可以先打表找规律,发现连续 ⌊ni⌋ 为定值的一段SG值是相等的,自己yy一下就发现很对。
有了这个性质就很简单了,暴力枚举块,枚举后继状态时连续的一段可以 O(1) …… 种复杂度大概是远小于 O(n−−√n−−√) 的一个东西…
这么理解的话,可以把一个石子,即一个白块看做一个独立的游戏。
现在只需求SG值。
SG(i)=mex{0,SG(2i),SG(2i) ^ SG(3i),SG(2i) ^ SG(3i) ^ SG(4i),...}
一般SG函数的题可以先打表找规律,发现连续 ⌊ni⌋ 为定值的一段SG值是相等的,自己yy一下就发现很对。
有了这个性质就很简单了,暴力枚举块,枚举后继状态时连续的一段可以 O(1) …… 种复杂度大概是远小于 O(n−−√n−−√) 的一个东西…
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=500005; int n,Q,ans,b[maxn],c[2][maxn],vis[maxn],clk,sqrt_n; inline int getSG(int x){ x=n/(n/x); if(x<=sqrt_n) return c[0][x]; else return c[1][n/x]; } void Solve(){ for(int i=1;i<=n;i=n/(n/i)+1) b[++b[0]]=n/(n/i); for(int i=b[0];i>=1;i--){ int x=b[i],now=0; clk++; vis[0]=clk; for(int j=x+x;j<=n;){ int t=(n/(n/j))/x*x, cnt=(t-j)/x+1; vis[now^getSG(j)]=clk; if(cnt&1) now^=getSG(j); j=t+x; } int res=0; while(vis[res]==clk) res++; if(x<=sqrt_n) c[0][x]=res; else c[1][n/x]=res; } } int main(){ freopen("bzoj4035.in","r",stdin); freopen("bzoj4035.out","w",stdout); scanf("%d",&n); sqrt_n=sqrt(n)+1; Solve(); scanf("%d",&Q); while(Q--){ int t,x; scanf("%d",&t); ans=0; while(t--) scanf("%d",&x), ans^=getSG(x); if(ans) puts("Yes"); else puts("No"); } return 0; }
相关文章推荐
- 【BZOJ 4035】 4035: [HAOI2015]数组游戏 (博弈)
- bzoj4035 [HAOI2015]数组游戏
- BZOJ 4035 [HAOI2015]数组游戏
- 【BZOJ4035】数组游戏,博弈论+分块乱搞
- [dfs序 树状数组] BZOJ 4034 [HAOI2015]T2
- [bzoj4035]数组游戏
- 【LOJ】#2126. 「HAOI2015」数组游戏
- [HAOI2015]数组游戏
- bzoj4035: [HAOI2015]T3
- BZOJ4033: [HAOI2015]T1
- BZOJ 3787: Gty的文艺妹子序列 [分块 树状数组!]
- BZOJ 4034 HAOI2015 T2 DFS序+线段树
- 【bzoj4034】 HAOI2015 T2 树链剖分+小变形
- BZOJ4034 [HAOI2015]T2
- bzoj 4033: [HAOI2015]树上染色【树形dp】
- bzoj3991 [SDOI2015]寻宝游戏
- bzoj 4034: [HAOI2015]树上操作(线段树+dfs序)
- bzoj 2301 [HAOI2011]Problem b(莫比乌斯反演+分块优化)
- 【BZOJ】4034 [HAOI2015]树上操作 树链剖分
- HAOI-2015-省队选拔题 T1[BZOJ 4033]