发现翻转相当于增加一个白格
对于一个白格子,它的SG值只与它还能跳的次数有关,如长度10,SG[4]=SG[5]。于是不同的状态只有sqrt(n)个。只要求出还能跳k步的位置的SG就能得到答案。
暴力DP即可,貌似O(n)能过
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 100005
using namespace std;
int n,k,sg[N],sg1[N],f[N],x,Ans;
int nxt(int x,int y){return (x==y)?y+1:y/(y/(x+1));}
int main()
{
scanf("%d%d",&n,&k);int sqn=sqrt(n);
//memset(sg,-1,sizeof sg);
//memset(sg1,-1,sizeof sg1);
for (int i=1,now;i<=n;i=nxt(i,n))
{
now=0;
for (int j=2;j<=i;j=nxt(j,i))
{
int t=i/j,p=(t<=sqn)?sg[t]:sg1[n/t];
f[now^p]=i;
if ((i/t-i/(t+1))&1) now^=p;
}
now=1;
while (f[now]==i) now++;
if (i<=sqn) sg[i]=now;
else sg1[n/i]=now;
}
while(k--)
{
Ans=0;int m;
scanf("%d",&m);
for (int i=1,t;i<=m;i++)
scanf("%d",&x),t=n/x,
Ans^=(t<=sqn)?sg[t]:sg1[n/t];
puts(Ans?"Yes":"No");
}
}