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

    Link

    ( ext{Solution:})

    回顾一下(Nim)游戏那个优美结论的( ext{conclusion:})

    将所有石子数量异或起来,若和为(0)则必败,否则必胜。(先手)

    那分以下情况考虑:

    首先是全(0:)此时必败,显然异或和为(0).

    然后是异或和不为(0)的状态:那我们必定可以找到一个(a_i),将它改变,使得异或和为(0).

    因为二进制异或下的某一位是(1)的话则一定有奇数个数在此处是(1).那么我们随意找一个,令异或和为(k).将(a_i o a_i ext{^} k)则这个数必然比原来的(a_i)小。因为最高位改变了。

    第三种情况是异或和为(0)时不存在一种移动使得下一步的异或和依旧是(0).

    因为如果让(a_i o a_i*)成立的话,则必然有(a_i*=a_i),是一个不合条件的移动。

    那么对于这个题:第一步用(Nim)和判断是不是必败,第二步枚举每一个队看看能不能修改即可。

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[5000010],s;
    pair<int,int>p;
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)scanf("%d",a+i);
    	for(int i=1;i<=n;++i)s^=a[i];
    	if(s==0){
    		puts("lose");
    		return 0;
    	}
    	for(int i=1;i<=n;++i){
    		int S=s;
    		S^=a[i];
    		if(a[i]>=S){
    			p.first=a[i]-S;
    			p.second=i;
    			a[i]-=p.first;
    			break;
    		}
    	}
    	printf("%d %d
    ",p.first,p.second);
    	for(int i=1;i<=n;++i)printf("%d ",a[i]);
    	puts("");
    	return 0;
    }
    
  • 相关阅读:
    20210312
    20210311
    20210310
    例5-1
    例5-2
    例4-12-2
    例4-12
    例4-11
    例4-10
    例4-9
  • 原文地址:https://www.cnblogs.com/h-lka/p/13059023.html
Copyright © 2011-2022 走看看