[2021.4.9多校省选模拟35]老魔杖 (博弈论,找规律(?))

题面

三大死亡圣器之一的老魔杖,被誉为最强魔杖,被 Harry 掰断后扔在悬崖下。

某一天,小 A 有幸在悬崖下捡到了这根魔杖,然而由于损坏严重,所以只能施一些简单的小魔法。恰好魔法界新兴起了一种小游戏,这个游戏是这样的:

地上有一些砖块,每一块的长度都是 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4 中的一个整数。每次一个人可以进行两种操作中的一种:

  1. 使用“粉身碎骨”咒,粉碎恰好 n n n 个长度为 n n n 的砖块。如果长度为 n n n 的砖块不足 n n n 个,则不能进行此操作。
  2. 使用“变形”咒,把一个长度大于 1 1 1 的砖块分为两个长度大于 0 0 0 的砖块。你必须保证分成的两个砖块长度都是正整数

当某个人无法使用魔法时即算输。

每次游戏的初始局面是随机生成的。然而小 A 还有一个迷之身份——欧捱儿,所以他可以作弊,当给出一个局面时,就知道先手能否必胜。

输入格式

输入的第一行包含一个整数 T T T, 表示数据组数。

接下来 T T T 行,每行四个非负整数 a , b , c , d a,b,c,d a,b,c,d,表示本组数据中长度为 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4 的砖块分别有多少个。

输出格式

输出 T T T 行,每行一个整数:1 表示先手必胜,0 表示先手必败。

样例输入

3
4 2 1 0
0 0 1 0
7 0 1 0

样例输出

1
1
0

数据范围与提示

对于 30% 数据满足: a + 2 b + 3 c + 4 d ≤ 10 a+2b+3c+4d\leq 10 a+2b+3c+4d10

对于 70% 数据满足: m a x { a , b , c , d } ≤ 14 max\{a,b,c,d\}\leq 14 max{a,b,c,d}14

对于 100% 数据满足: 1 ≤ T ≤ 10 , m a x { a , b , c , d } ≤ 1 0 10000 1\leq T\leq10,max\{a,b,c,d\}\leq10^{10000} 1T10,max{a,b,c,d}1010000

题解

看到 100% 的数据就被吓到了,隐约觉得这是个结论题。

再看 70% 的数据,居然这么小!于是直接打了 DP 骗分跑路。

这里的 d p [ a ] [ b ] [ c ] [ d ] dp[a][b][c][d] dp[a][b][c][d] 表示四种砖块数量各是 a , b , c , d a,b,c,d a,b,c,d 时的状态,注意上界: a ≤ 140 , b ≤ 62. c ≤ 32 , d ≤ 14 a\leq 140,b\leq 62.c\leq 32,d\leq 14 a140,b62.c32,d14 ,以及计算顺序就行了。

但是这题不能就这么完了啊。我们得寻找结论。比起麻烦的猜想和推导,还是找规律靠谱些。

于是我把 m a x { a , b , c , d } ≤ 14 max\{a,b,c,d\}\leq 14 max{a,b,c,d}14 的 dp 值都打了出来,发现对于固定的 b , c , d b,c,d b,c,d a a a 从小(从0)变到大会让 DP 值为 { 1 , 1 , 1 , 1... } \{1,1,1,1...\} {1,1,1,1...} { 1 , 0 , 1 , 0 , . . . } \{1,0,1,0,...\} {1,0,1,0,...} { 0 , 1 , 0 , 1 , . . . } \{0,1,0,1,...\} {0,1,0,1,...} 三种情况 ,于是我又分别把满足三种变化方式的 b , c , d b,c,d b,c,d 分别打了出来:

  1. 第一种 { 1 , 1 , 1 , 1 , . . . } \{1,1,1,1,...\} {1,1,1,1,...}:满足 ( b + d ) % 3 = 2 (b+d)\%3=2 (b+d)%3=2
  2. 第二种 { 1 , 0 , 1 , 0 , . . . } \{1,0,1,0,...\} {1,0,1,0,...}:满足 ( b + d ) % 3 = ( c + 1 ) % 2 (b+d)\%3=(c+1)\%2 (b+d)%3=(c+1)%2
  3. 第三种 { 0 , 1 , 0 , 1 , . . . } \{0,1,0,1,...\} {0,1,0,1,...}:满足 ( b + d ) % 3 = c % 2 (b+d)\%3=c\%2 (b+d)%3=c%2

所以规律就找到了!当且仅当 ( b + d ) % 3 = 2 (b+d)\%3=2 (b+d)%3=2 ( b + d ) % 3 = ( c + a + 1 ) % 2 (b+d)\%3=(c+a+1)\%2 (b+d)%3=(c+a+1)%2 时先手必胜!

CODE

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 10005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
#define mymax(a,b,c,d) max(max((a),(b)),max((c),(d)))
LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-')f=-f;s = getchar();}
	while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
	return f * x;
}
const int MOD = 1000000007;
int n,m,i,j,s,o,k;
bool dp[145][65][35][16];// 140 , 63 , 33 , 14
char A[MAXN],B[MAXN],C[MAXN],D[MAXN];
int main() {
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	int T = read();
	memset(dp,1,sizeof(dp));
	dp[0][0][0][0] = 0;
	for(int d = 0;d <= 14;d ++) {
		for(int c = 0;c <= 33;c ++) {
			for(int b = 0;b <= 63;b ++) {
				for(int a = 0;a <= 140;a ++) {
					if(a+b+c+d && a+2*b+3*c+4*d <= 140) {
						dp[a][b][c][d] = 1;
						if(a>0) dp[a][b][c][d] &= dp[a-1][b][c][d];
						if(b>1) dp[a][b][c][d] &= dp[a][b-2][c][d];
						if(c>2) dp[a][b][c][d] &= dp[a][b][c-3][d];
						if(d>3) dp[a][b][c][d] &= dp[a][b][c][d-4];
						if(d) {
							dp[a][b][c][d] &= dp[a+1][b][c+1][d-1];
							dp[a][b][c][d] &= dp[a][b+2][c][d-1];
						}
						if(c) {
							dp[a][b][c][d] &= dp[a+1][b+1][c-1][d];
						}
						if(b) {
							dp[a][b][c][d] &= dp[a+2][b-1][c][d];
						}
						dp[a][b][c][d] ^= 1;
//						if(1||(a+b*2+c*3+d*4) & 1) printf("%d ",dp[a][b][c][d]);
					}
				}
//				if(dp[0][b][c][d] == 0 && dp[1][b][c][d] == 1) printf("bcd: %d %d %d",b,c,d);
//				ENDL;
			}
//			ENDL;
		}
//		ENDL;
	}
	while(T --) {
		int la,lb,lc,ld;
		scanf("%s", A + 1);
		la = strlen(A + 1);
		
		scanf("%s", B + 1);
		lb = strlen(B + 1);
		
		scanf("%s", C + 1);
		lc = strlen(C + 1);
		
		scanf("%s", D + 1);
		ld = strlen(D + 1);
		int a = 100,b = 100,c = 100,d = 100;
		if(mymax(la,lb,lc,ld) <= 3) {
			sscanf(A+1,"%d",&a);
			sscanf(B+1,"%d",&b);
			sscanf(C+1,"%d",&c);
			sscanf(D+1,"%d",&d);
		}
		if(mymax(a,b,c,d) <= 14) {
			printf("%d\n",dp[a][b][c][d]);
			continue;
		}
		a = b = c = d = 0;
		for(int i = 1;i <= la;i ++) a = (a*10+(A[i]-'0')) % 2;
		for(int i = 1;i <= lc;i ++) c = (c*10+(C[i]-'0')) % 2;
		for(int i = 1;i <= lb;i ++) b = (b*10+(B[i]-'0')) % 3;
		for(int i = 1;i <= ld;i ++) d = (d*10+(D[i]-'0')) % 3;
		if((b+d)%3 == 2 || (b+d)%3 == (c+a+1)%2) printf("1\n");
		else printf("0\n");
	}
	return 0;
}
// bs: (b+d)%3 = 2 , ((b+d)%3 = (c+a+1)%2)
posted @ 2021-04-09 15:00  DD_XYX  阅读(65)  评论(0)    收藏  举报