#SG函数,整除分块#洛谷 3235 [HNOI2014] 江南乐

题目传送门


分析

仍然是 SG 函数的异或值,这时需要枚举堆数 \(m\),那么分解后只可能为 \(\lfloor\frac{x}{m}\rfloor\)\(\lfloor\frac{x}{m}\rfloor+1\),且数目分别为 \(x\bmod m,m-x\bmod m\)

而 SG 函数与数目的奇偶性有关,因此整除分块后根据奇偶性记忆化搜索递归下去即可求出答案。


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=100011;
int sg[N],v[N],T,F,n,ans;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans; 
}
inline signed Sg(int n){
	if (n<F) return 0;
	if (~sg[n]) return sg[n];
	for (rr int l=2,r;l<=n;l=r+1){
		r=n/(n/l);
		rr int upp=n%l,low=l-upp;
		v[((low&1)?Sg(n/l):0)^((upp&1)?Sg(n/l+1):0)]=n;
		if (l<r){
			++l,upp=n%l,low=l-upp;
			v[((low&1)?Sg(n/l):0)^((upp&1)?Sg(n/l+1):0)]=n;
		}
	}
	for (sg[n]=0;v[sg[n]]==n;++sg[n]);
	return sg[n];
}
signed main(){
	memset(sg,-1,sizeof(sg));
	for (T=iut(),F=iut();T;--T){
		n=iut(),ans=0;
		for (rr int i=1;i<=n;++i) ans^=Sg(iut());
		putchar(ans?49:48),putchar(32);
	}
	return 0;
} 
posted @ 2025-06-29 12:20  lemondinosaur  阅读(9)  评论(0)    收藏  举报