• bzoj 3895: 取石子


    $ color{#0066ff}{ 题目描述 }$

    Alice和Bob两个好朋含友又开始玩取石子了。游戏开始时,有N堆石子

    排成一排,然后他们轮流操作(Alice先手),每次操作时从下面的规则中任选一个:

    ·从某堆石子中取走一个

    ·合并任意两堆石子

    不能操作的人输。Alice想知道,她是否能有必胜策略。

    (color{#0066ff}{输入格式})

    第一行输入T,表示数据组数。

    对于每组测试数据,第一行读入N。

    接下来N个正整数a1,a2…an,表示每堆石子的数量。

    (color{#0066ff}{输出格式})

    对于每组测试数据,输出一行。

    输出YES表示Alice有必胜策略,输出NO表示Alice没有必胜策略。

    (color{#0066ff}{输入样例})

    3
    3
    1 1 2
    2
    3 4
    3
    2 3 5
    

    (color{#0066ff}{输出样例})

    YES
    NO
    NO
    

    (color{#0066ff}{数据范围与提示})

    100%的数据满足T<=100, N<=50. ai<=1000

    (color{#0066ff}{题解})

    如果合并,石子数不变,如果取,石子数-1,表面上看,结局已经注定,跟操作数的奇偶有关

    然而,会有这样的情况,比如1和1

    合并,那么操作数-1,如果取走一个1,那么操作数-2!!!这是不一样的

    于是我们发现,状态实际上只跟1的堆数和操作数有关

    所以,设(sg[x][y])表示当前有x堆是1,除了1的那些堆的操作数共y次的SG值

    然后分别讨论所有情况进行转移

    因为不涉及多个游戏的合并,所以sg不是0就是1,就不用开vis数组记录什么东西了

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    int n;
    int sg[55][52050];
    int work(int x, int y) {
    	if(!x) return y & 1;
    	if(y == 1) return sg[x][y] = work(x + 1, y - 1);
    	if(~sg[x][y]) return sg[x][y];
    	if(x && !work(x - 1, y)) return sg[x][y] = 1;
    	if(x && y && !work(x - 1, y + 1)) return sg[x][y] = 1;
    	if(x >= 2 && !work(x - 2, y + 2 + (y > 0))) return sg[x][y] = 1;	
    	if(y && !work(x, y - 1)) return sg[x][y] = 1;
    	//拿走一个1
    	//1跟非1合并
    	//两个1合并
    	//某个非1堆拿走1个或合并两个非1堆
    	return sg[x][y] = 0;
    }
    int main() {
    	memset(sg, -1, sizeof sg);
    	for(int T = in(); T --> 0;) {
    		n = in();
    		int x = 0, y = 0, z;
    		for(int i = 1; i <= n; i++) {
    			z = in();
    			x += (z == 1);
    			y += (z > 1) * z;
    		}
    		y += n - x - 1;
    		if(y == -1) y++;
    		printf(!work(x, y)? "NO
    " : "YES
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    常用命令
    经典算法
    框架
    计算机网络
    设计模式
    JVM
    数据库
    多线程
    Java中HashMap的底层实现原理
    构建大小顶堆
  • 原文地址:https://www.cnblogs.com/olinr/p/10465652.html
Copyright © 2020-2023  润新知