zoukankan      html  css  js  c++  java
  • 【LG P1427】取火柴游戏

    推导过程

    这是经典 Nim 游戏模型。

    这个游戏的 SG 值就是各堆数量的异或和,当 SG 为 (0) 时先手必败,否则先手就要把 SG 变为 (0)

    先检验 SG 值,如果是 (0) 输出 lose,否则我们按照以下原则行动:

    (n) 个数的异或值不为 (0),现在要减少一个数使异或值为 (0)

    假设 (n) 个数:(a_1,a_2,dots,a_n),且 (a_1operatorname{xor}a_2operatorname{xor}dotsoperatorname{xor}a_n=k),那么我们可以对一个数进行操作。

    假设这个数是 (a_i),设 (a_ioperatorname{xor}k=a'),则:

    [egin{align*} &a'operatorname{xor}a_1operatorname{xor}a_2operatorname{xor}...operatorname{xor}a_{i-1}operatorname{xor}a_{i+1}operatorname{xor}dotsoperatorname{xor}a_n\ &=a_1operatorname{xor}a_2operatorname{xor}a_3operatorname{xor}...operatorname{xor}a_noperatorname{xor}k\ &=koperatorname{xor}k\ &=0 end{align*} ]

    所以我们只需要从头到尾检验每个数异或 (k) 的值是否比它小(因为是要减少),遇到小的直接输出 (a_i-a_ioperatorname{xor}k) 即可。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e5+5;
    int a[N];
    int main() {
    	int n;
    	scanf("%d",&n);
    	int x=0;
    	for(int i=1; i<=n; i++) {
    		scanf("%d",a+i),x^=a[i];
    	}
    	if(!x) {
    		puts("lose");
    		return 0;
    	}
    	for(int i=1; i<=n; i++) {
    		if((a[i]^x)>=a[i]) {
    			continue;
    		}
    		printf("%d %d
    ",a[i]-(a[i]^x),i),a[i]^=x;
    		break;
    	}
    	for(int i=1; i<=n; i++) {
    		printf("%d ",a[i]);
    	}
    	return 0;
    }
    

    来源

    题解 P1247 【取火柴游戏】 - revenger 的博客 - 洛谷博客

    知识共享许可协议

    本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

    限于本人水平,如果文章有表述不当之处,还请不吝赐教。

  • 相关阅读:
    HDU
    HDU
    西电OJ
    西电OJ
    西电OJ
    USACO 2.1-Healthy Holsteins
    USACO 2.1-Sorting a Three-Valued Sequence
    HDU
    UVA
    codeforces 811A Vladik and Courtesy
  • 原文地址:https://www.cnblogs.com/Sam2007/p/15029482.html
Copyright © 2011-2022 走看看