luoguP3235 [HNOI2014]江南乐 数论分块 + 博弈论


感觉其实很水?

题目就是一个Multi SG游戏,只需要预处理出所有的\(sg\)值即可\(O(Tn)\)计算

对于计算\(sg[n]\)而言,显然我们可以枚举划分了\(x\)堆来查看后继状态

那么,有\(n\;mod\;x\)\(\left \lfloor \frac{n}{x} \right \rfloor + 1\)的堆以及\(x - n\;mod\;x\)\(\left \lfloor \frac{n}{x} \right \rfloor\)的堆

暴力转移就是\(O(10^{10})\)

显然上面可以数论分块,再讨论一下奇偶即可

复杂度\(O(10^5 \sqrt 10^5)\)


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)

const int sid = 2e5 + 5;
	
int T, F, tim;
int sg[sid], mex[sid];
	
inline void init() {
	rep(i, F, 100000) {
		++ tim;
		for(ri ii = 2, jj; ii <= i; ii = jj + 1) {
			jj = i / (i / ii); 
			int p = i / ii, S = i - p * ii, S2 = ii - S, SG = 0;
			if(S & 1) SG ^= sg[p + 1];
			if(S2 & 1) SG ^= sg[p]; mex[SG] = tim;
			if(ii + 1 > jj) continue;
			S = i - p * (ii + 1); S2 = (ii + 1) - S; SG = 0;
			if(S & 1) SG ^= sg[p + 1];
			if(S2 & 1) SG ^= sg[p]; mex[SG] = tim;
		}
		rep(j, 0, 100000) if(mex[j] != tim) 
		{ sg[i] = j; break; }
	}
}
	
int main() {
	cin >> T >> F;
	init();
	while(T --) {
		int n, x, SG = 0;
		cin >> n;
		rep(i, 1, n) { cin >> x; SG ^= sg[x]; }
		printf("%d ", SG ? 1 : 0);
	}
	return 0;
}
posted @ 2018-12-20 21:53  remoon  阅读(148)  评论(0编辑  收藏  举报