题目链接:https://cn.vjudge.net/problem/ZOJ-3057 

There are three piles of beans. TT and DD pick any number of beans from any pile or the same number from any two piles by turns. Who get the last bean will win. TT and DD are very clever.

 

Input

 

Each test case contains of a single line containing 3 integers a b c, indicating the numbers of beans of these piles. It is assumed that 0 <= a,b,c <= 300 and a + b + c > 0.

 

Output

 

For each test case, output 1 if TT will win, ouput 0 if DD will win.

 

Sample Input

 

1 0 0
1 1 1
2 3 6
 

Sample Output

 

1
0
0
这道题目的意思很简单就是有三堆石子,一次操作可以拿一堆石子中的任意的石子数目,也可以任意选择两堆石子,拿走相同数量的石子,问一下先手是否是有必胜的策略如果有的话就输出1,否则的话就输出0;

这道题目如果是采用原始的求算sg的方法的话,就是对于当前的状态求算他的后继状态的话会发现,时间复杂度是会超时的,因为我们每次都需要初始化一遍标记数组,但是我们会发现这道题目有一个特点就是只需要判断当前是否是必胜状态就可以了,不需要一定要知道这个状态的sg值,只是判断是否是必胜的状态,怎么判断呢;

我们可以这么想如果当前的状态是必输的状态的话,那么通过一次操作可以到达它的状态不就是必胜状态了吗,这样的的话我们就可以省掉标记直接把后继状态是必输的状态标记为必胜就可以了,其实这道题目跟前面博客的一道题目是很相似的就是对多堆石子来操作;
原文:https://blog.csdn.net/qq_39792342/article/details/83278267 

#include<cstdio>
#include<cstring>
using namespace std;
bool sg[305][305][305];
void f(){
	for(int a=0;a<=300;a++){
		for(int b=0;b<=300;b++){
			for(int c=0;c<=300;c++){
				if(!sg[a][b][c]){
					for(int i=1;i+a<=300;i++) sg[i+a][b][c]=true;
					for(int i=1;i+b<=300;i++) sg[a][i+b][c]=true;
					for(int i=1;i+c<=300;i++) sg[a][b][i+c]=true;
					for(int i=1;i+a<=300&&i+b<=300;i++) sg[i+a][i+b][c]=true;
					for(int i=1;i+a<=300&&i+c<=300;i++) sg[i+a][b][i+c]=true;
					for(int i=1;i+b<=300&&i+c<=300;i++) sg[a][i+b][i+c]=true;
				}
			}
		}
	}
}
int main(){
	f();
	int a,b,c;
	while(~scanf("%d%d%d",&a,&b,&c)){
		if(sg[a][b][c]) printf("1\n");
		else printf("0\n");
	}
	return 0;
}