zoukankan      html  css  js  c++  java
  • 题解 P1247 【取火柴游戏】

    题目链接

    Solution 取火柴游戏

    题目大意:(Nim) 游戏输方案

    博弈论,(Nim) 游戏


    分析:

    首先(Nim)和定理,(Nim)游戏存在先手必胜状态,当且仅当(a_1 igoplus a_2 igoplus a_3 dots igoplus a_n eq 0)

    分析,首先最终状态所有物品取完(Nim)和显然为(0),为必败状态,反过来对手就是必胜状态了

    对于(a_1 igoplus a_2 igoplus a_3 dots igoplus a_n eq 0),我们假设(a_1 igoplus a_2 igoplus a_3 dots igoplus a_n=k),我们任选一个(a_i)将其异或上(k)即可

    根据定义,一定有奇数个(a_i)最高位和(k)最高位相同,因此异或后比原来小,是个合法操作

    对于(a_1 igoplus a_2 igoplus a_3 dots igoplus a_n = 0),一定不存在一种方案使得操作后仍有(a_1 igoplus a_2 igoplus a_3 dots igoplus a_n = 0),因为这样操作后两数相等不是合法操作,也就是说

    (a_1 igoplus a_2 igoplus a_3 dots igoplus a_n eq 0)时是必胜状态,它可以转移到

    (a_1 igoplus a_2 igoplus a_3 dots igoplus a_n = 0)是必败状态

    而必败状态只能转移到必胜状态,根据归纳法得证

    再来看输方案,我们枚举每一个(a_i)检查异或上(k)后是否合法即可

    #include <cstdio>
    #include <cctype>
    using namespace std;
    const int maxn = 5e5 + 100;
    inline int read(){
    	int x = 0;char c = getchar();
    	while(!isdigit(c))c = getchar();
    	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    	return x; 
    }
    int val[maxn],n,sum,ansa,ansb;
    int main(){
    	n = read();
    	for(int i = 1;i <= n;i++)
    		sum ^= val[i] = read();
    	if(sum == 0)return puts("lose"),0;
    	for(int i = 1;i <= n;i++){
    		int target = sum ^ val[i];
    		if(target > val[i])continue;
    		ansa = val[i] - target;
    		ansb = i;
    		break;
    	}
    	printf("%d %d
    ",ansa,ansb);
    	val[ansb] -= ansa;
    	for(int i = 1;i <= n;i++)
    		printf("%d%c",val[i],i == n ? '
    ' : ' ');
    	return 0;
    }
    
  • 相关阅读:
    如何面试前端工程师!
    CSS实现背景透明,文字不透明(各浏览器兼容)
    IE6中伪类:hover的使用及BUG
    jQuery UIdraggable参数学习
    PHP与正则表达式 2 :一些修饰符与preg_match_all
    通过apktool获取apk package name(包名)以及activity name
    jquery.ui.draggable中文文档
    无法加载php_curl.dll解决办法
    ubuntu命令查询版本和内核版本
    linux zip, unzip命令详解[ubuntu]
  • 原文地址:https://www.cnblogs.com/colazcy/p/11732651.html
Copyright © 2011-2022 走看看