#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;
}

浙公网安备 33010602011771号