VIJOS1655 萌萌的糖果博弈
? 解题记录 ? ? 博弈论 ? ? SG函数 ? ? VIJOS ?    2018-01-28 12:10:13    340    0    0

背景

用糖果来引诱小朋友学习是最常用的手法,绵羊爸爸就是用糖果来引诱萌萌学习博弈的。

描述

他把糖果分成了两堆,一堆有A粒,另一堆有B粒。他让萌萌和他一起按照下面的规则取糖果:每次可以任意拿走其中一堆糖果;如果这时候另一堆糖果数目多于1粒,就把它任意分成两堆,否则就把剩下的一粒糖果取走并获得这次博弈的胜利。胜利者将获得所有的糖果。萌萌想要得到所有的糖果,而绵羊爸爸想把糖果留下以便下一次利用。现在由萌萌先取糖果,旁观的小朋友们想知道萌萌是否有必胜策略。

格式

输入格式

本题有多组测试数据(不超过100组)。每组数据包括两行,第一行为A,第二行为B。1 ≤ A,B ≤ 2^127。输入数据以一个 -1 结束。

输出格式

每组数据对应一行输出。如果萌萌获胜则输出"MengMeng",否则输出"SheepDaddy"(不包括引号)。

样例1

样例输入1

1
2
2
3
-1
Copy

样例输出1

MengMeng
SheepDaddy
Copy

限制

所有测试点时限均为1000ms

    向手推大佬低头……Orz。这道题可以用SG函数找到规律:只要两堆石子都满足石子数对5取模余数为2或3,那么就是羊爸赢了。下面是SG函数的程序和AC代码。

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 30;
int sg[maxn * 2 + 5][maxn * 2 + 5];
bool vis[10000];
int main() {
	for(int i = 1; i <= maxn; ++i)
		sg[i][1] = sg[1][i] = 1;
	for(int sig = 4; sig <= maxn * 2; ++sig) 
		for(int j = 2; j < sig - 1; ++j){
			int p;
			int i = sig - j;
			for(int k = 1; k < i; ++k) {
				int l = i - k;
				vis[sg[k][l]] = 1;
			}
			for(int k = 1; k < j; ++k) {
				int l = j - k;
				vis[sg[k][l]] = 1;
			}
			for(p = 0; p < maxn; ++p)	{
				if(!vis[p]) break;
			}
			sg[i][j] = p;
			for(int k = 1; k < i; ++k) {
				int l = i - k;
				vis[sg[k][l]] = 0;
			}
			for(int k = 1; k < j; ++k) {
				int l = j - k;				vis[sg[k][l]] = 0;
			}
		}
	for(int i = 1; i <= maxn; ++i){
		for(int j = 1; j <= maxn; ++j)
			printf("%d ", sg[i][j] ? 1 : 0 );
		printf("\n");
	}
	return 0;
}

AC代码 19ms:

#include<cstdio>
#include<cstdlib>
using namespace std;

inline void read(int & ret) {
	char c = getchar();if(c == '-') exit(0);
	while(c > '9' || c < '0') c = getchar();
	while(c <= '9' && c >= '0') {
		if(c <= '9' && c >= '0') ret = c - '0';
		c = getchar(); 
	}
}

int main() {
	int a, b;
	while(1) {
		read(a), read(b);
		puts((a % 5 == 2 | a % 5 == 3)&(b % 5 == 2 | b % 5 == 3)?"SheepDaddy":"MengMeng");
	}
}

 

上一篇: BZOJ2226: [Spoj 5971] LCMSum

下一篇: 洛谷P2296 寻找道路

340 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航