这题显然把每个白格子看成一个子游戏
一个白格子$x$的$sg$值是$mex{[0,sg[2x],sg[2x] XOR sg[3x].....]}$
打表发现一个数的$sg$值只和$n/x$有关,然后分块乱搞就行了。
一开始开了个$map$,一直$TLE$,换成两个数组就过了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <map> 7 #include <ctime> 8 #define N 100050 9 using namespace std; 10 bool bo[257]; 11 int n,m,T,sg1[N],sg2[N]; 12 int getsg(int x){ 13 int now=0; 14 memset(bo,0,sizeof bo); 15 int y=n/x; 16 for(int i=2,j;i<=y;i=j+1){ 17 j=y/(y/i); 18 int sg=(i*x>m)?sg1[n/(i*x)]:sg2[i*x]; 19 if((j-i+1)&1)now^=sg; 20 bo[now^sg]=1;bo[now]=1; 21 } 22 for(int i=1;;i++)if(!bo[i])return i; 23 } 24 int tot; 25 int main(){ 26 scanf("%d",&n); 27 m=sqrt(n); 28 for(int i=n,j;i;i=j-1){ 29 j=n/((n/i)+1)+1; 30 if(i>m)sg1[n/i]=getsg(i); 31 else sg2[i]=getsg(i); 32 } 33 scanf("%d",&T); 34 int num,ans; 35 while(T--){ 36 scanf("%d",&num);ans=0; 37 for(int i=1,x;i<=num;i++){ 38 scanf("%d",&x); 39 x=(x>m)?sg1[n/x]:sg2[x]; 40 ans^=x; 41 } 42 if(ans)puts("Yes"); 43 else puts("No"); 44 } 45 return 0; 46 }