博弈的关键就是求sg。
此题为优化暴力求sg的过程。
有些题是找规律或利用性质求sg
当然也有个别题直接抓住性质不用求sg,如bzoj4975
求sg的关键:sg=mex{后继状态}
sg=xorsum{当前所有独立状态}
打表找规律常开脑洞
//调题时仔细改错,不要打错字符
#include<bits/stdc++.h>
using namespace std;
#define maxn 100020
int sg[maxn],vis[maxn],cnt[maxn];
int n,F,T,a[maxn],dfstime;
int getsg(int x){
if ( x < F ) return sg[x] = 0;
if ( sg[x] != -1 ) return sg[x];
//用时间戳打标记,不用清空数组
//一定要先递归再求当前sg,要不然cnt的标记会被覆盖
for (register int i = 2,next ; i <= x ; i = next + 1){
getsg(x / i + 1);
getsg(x / i );
next = x / (x / i);
}
++dfstime;
for (register int i = 2,next ; i <= x ; i = next + 1){
int a = x % i , b = i - a , cur = 0;
next = x / (x / i);
if ( a & 1 ) cur = sg[x / i + 1];
if ( b & 1 ) cur ^= sg[x / i];
cnt[cur] = dfstime;
if ( next != i ){
a = x % (i + 1) , b = i + 1 - a , cur = 0;
if ( a & 1 ) cur = sg[x / i + 1];
if ( b & 1 ) cur ^= sg[x / i];
cnt[cur] = dfstime;
}
}
sg[x] = 0;
for (register int i = 0 ; cnt[i] == dfstime ; i++){
sg[x]++;
}
return sg[x];
}
void init(){
for (int i = 100000 ; i >= F ; i--) sg[i] = -1;
// cout<<getsg(100)<<endl;
// for (int i = 100000 ; i >= 0 ; i--) sg[i] = getsg(i);
//cout<<getsg(100)<<endl;
// for (int i = 0 ; i <= 5 ; i++) cout<<sg[i]<<" ";
// cout<<endl;
}
int main(){
freopen("input.txt","r",stdin);
// freopen("1.out","w",stdout);
scanf("%d %d",&T,&F);
init();
while ( T-- ){
int ans = 0;
scanf("%d",&n);
for (int i = 1 ; i <= n ; i++) scanf("%d",&a[i]) , ans ^= getsg(a[i]);
if ( ans ) cout<<1<<" ";
else cout<<0<<" ";
}
return 0;
}