标签:lim int sg 博弈论 cin HAOI2015 ans SG
有一个长度为N的数组,甲乙两人在上面进行这样一个游戏:首先,数组上有一些格子是白的,有一些是黑的。然后两人轮流进行操作。每次操作选择一个白色的格子,假设它的下标为x。接着,选择一个大小在1~n/x之间的整数k,然后将下标为x、2x、...、kx的格子都进行颜色翻转。不能操作的人输。现在甲(先手)有一些询问。每次他会给你一个数组的初始状态,你要求出对于这种初始状态他是否有必胜策略。
Solution
用暴力 SG 打个表,发现一段一段的 SG 值都是相同的,所以套个整除分块即可
#include <bits/stdc++.h>
using namespace std;
const int N = 400005;
int n,q,lim,sg[2][N],pos[N],u[N];
int SG(int x) {
x=n/(n/x);
if(x>lim) return sg[1][n/x];
else return sg[0][x];
}
void presolve() {
int cnt=0;
for(int i=1,j;i<=n;i=j+1) {
j=n/(n/i);
pos[++cnt]=j;
}
while(cnt) {
int x=pos[cnt], now=0, mex=1;
u[now]=cnt;
for(int i=x+x,j;i<=n;i=j+x) {
j=n/(n/i)/x*x;
u[now^SG(j)]=cnt;
if((j-i)/x&1^1) now^=SG(j);
}
while(u[mex]==cnt) ++mex;
if(x>lim) sg[1][n/x]=mex;
else sg[0][x]=mex;
--cnt;
}
}
signed main() {
ios::sync_with_stdio(false);
cin>>n>>q;
lim=sqrt(n);
presolve();
while(q--) {
int m,x,ans=0;
cin>>m;
while(m--) {
cin>>x;
ans^=SG(x);
}
if(ans) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
标签:lim,int,sg,博弈论,cin,HAOI2015,ans,SG 来源: https://www.cnblogs.com/mollnn/p/12400733.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。