简单SG函数及应用

// 简单SG函数模板

int sg[maxn];
bool vis[maxn];
int SG(int n) {
	memset(sg, 0, sizeof sg);
	sg[0] = 0;// 初始状态
	for (int i = 1; i <= n; ++i) {// 递推
		memset(vis, 0, sizeof vis);
		for (int j = 0; j < i; ++i) {// 相关状态
			int tmp = sg[j] ^ sg[i - j];// 如果可以分成多个子游戏, 值就是他们的sg异或
			vis[tmp] = 1;
		}
		for (int j = 0; ; ++j) if (!vis[j]) {
			sg[i] = j; break;
		}
	}
	return sg[n];
}

例题:HDU - 3980

const int maxn = 2e2 + 10;
int sg[1010];
bool vis[1010];
int SG(int n, int m) {
	memset(sg, 0, sizeof sg);
	for (int i = m; i <= n; ++i) {
		memset(vis, 0, sizeof vis);
		for (int j = m; j <= i; ++j) {
			int tmp = sg[j - m] ^ sg[i - j];// 两个sg游戏相异或
			vis[tmp] = 1;
		}
		for (int j = 0; ; ++j)
			if (!vis[j]) {
				sg[i] = j;
				break;
			}
	}
	return sg[n];
}

int cas = 1;
signed main() {
	int t; scanf("%d", &t);
	while (t--) {
		int n, m;
		scanf("%d %d", &n, &m);
		printf("Case #%d: ", cas++);
		if (m > n)	puts("abcdxyzk");
		else {
			n -= m;// 一开始是环,怎么拿连续m个都是等价的
			// 所以直接拿掉m个后环变成直线,然后以后手为先手
			if(m > n)	puts("aekdycoin");
			else {
				SG(n, m);
				if (sg[n])	puts("abcdxyzk");
				else puts("aekdycoin"); 
				//printf("%d\n", sg[n]);
			}
		}
	}
	return 0;
}

HDU - 2147

const int maxn = 2e3 + 10;
short sg[maxn][maxn];
bool vis[maxn];

int SG(int n, int m) {
	sg[1][1] = 0; sg[2][1] = sg[2][2] = 1;
	for (int i = 3; i <= n; ++i) {
		sg[i][1] = !sg[i - 1][1];
		for (int j = 2; j <= i; ++j) {// 很明显的只有最多四种状态
			vis[0] = 0; vis[1] = 0; vis[2] = 0; vis[3] = 0;
			vis[sg[i][j - 1]] = vis[sg[i - 1][j - 1]] = 1;
			if (i != j)	vis[sg[i - 1][j]] = 1;
			for (int k = 0; ; ++k)	if (!vis[k]) {
				sg[i][j] = k; break;
			}
		}
	}
	return sg[n][m];
}

signed main() {
	int n, m;
	//SG(2000, 2000);
	//for (int i = 1; i <= 10; ++i) {
	//	for (int j = 1; j <= i; ++j) {
	//		printf("%d%c", sg[i][j], j == i ? '\n' : ' ');
	//	}
	//}
	while (~scanf("%d %d", &n, &m), n + m) {
		n %= 2; m %= 2;
		if(!(n && m)) puts("Wonderful!");
		else puts("What a pity!");
		//if (n < m)	swap(n, m);
		//if (sg[n][m])	puts("Wonderful!");
		//else puts("What a pity!");
	}
	return 0;
}

POJ - 2960

const int maxn = 1e2 + 10;
int heap[maxn][maxn];
int sg[maxn * maxn];
bool vis[maxn];

int s[maxn];
int k;
int SG(int n) {
	memset(sg, 0, sizeof sg);
	for (int i = 1; i <= n; ++i) {
		memset(vis, 0, sizeof vis);
		for (int j = 0; j < k && s[j] <= i; ++j)
			vis[sg[i - s[j]]] = 1;
		for (int j = 0; ; ++j)	if (!vis[j]) {
			sg[i] = j; break;
		}
	}
	return sg[n];
}

signed main() {
	while (~scanf("%d", &k), k) {
		for (int i = 0; i < k; ++i)	scanf("%d", &s[i]);
		sort(s, s + k);
		int m; scanf("%d", &m);
		int maxx = -1;
		for (int i = 0; i < m; ++i) {
			scanf("%d", &heap[i][0]);
			for (int j = 1; j <= heap[i][0]; ++j) {
				scanf("%d", &heap[i][j]); maxx = max(maxx, heap[i][j]);
			}
		}
		SG(maxx);
		for (int i = 0; i < m; ++i) {
			int tmp = 0;
			for (int j = 1; j <= heap[i][0]; ++j) tmp ^= sg[heap[i][j]];// 多堆异或和
			if (tmp)	printf("W");
			else printf("L");
		}
		puts("");
	}
	return 0;
}

HDU - 1847

posted @ 2021-02-04 17:48  wansheking  阅读(34)  评论(0)    收藏  举报