[HNOI2014]江南乐

Posted by Dispwnl on April 21, 2019

题目

题解

明显的$Multi-SG$游戏,可以枚举堆数然后判断各种大小堆的个数的奇偶性,这样复杂度是$O({\max(a_i)}^2)$的

发现讨论各种大小的堆的个数没有意义,因为只会有两种堆的大小

最小堆的大小在枚举堆数的时候是类似一个整除分块,某些堆数的最小堆大小可能一样,这样可以分最小堆个数为奇数和偶数讨论

预处理跑不过……只能记忆化搜索

代码

# include<iostream>
# include<cstring>
# include<cstdio>
# include<algorithm>
using namespace std;
const int MAX=1e5+5;
int T,n,F,Mx=-1,mx;
int a[MAX],sg[MAX],use[MAX];
int read()
{
	int x(0);
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);x=x*10+ch-48,ch=getchar());
	return x;
}
int SG(int x)
{
	if(sg[x]!=-1) return sg[x];
	for(int l=2,r;l<=x;l=r+1)
	  {
	  	r=x/(x/l);
	  	for(int i=l,N,o,k;i<=min(l+1,r);++i)
	  	  {
	  	  	N=x/i;
	  	  	if(N*i==x) o=(i&1)?SG(N):0;
	  		else k=x-N*i,o=((k&1)?SG(N+1):0)^((i-k&1)?SG(N):0);
	  		use[o]=x;
		  }
	  }
	for(int j=0;;++j)
	  if(use[j]!=x) return sg[x]=j;
}
int main()
{
	T=read(),F=read();
	memset(sg,-1,sizeof(sg));
	for(int i=0;i<F;++i)
	  sg[i]=0;
	while(T--)
	{
		n=read();
		int x=0;
		for(int i=1;i<=n;++i)
		  x^=SG(read());
		x?printf("1 "):printf("0 ");
	}
	return 0;
}