P1247 取火柴游戏(nim游戏+取第一个数判断)

传送门

题目描述:

思路:nim游戏,判断能不能先手赢就是直接把所有值异或,为0说明无论如何取,另一个人都能找到一个与之相同数目的火柴堆,无法胜利/必输。

那么第一步取那个呢?

假设x是1-n所有数目的异或和,那么我们只需要将x再^x就是0了,轮到下一个人就必输,如何实现呢?

我们只需要找到一个满足x^a[i]<=a[i]的位置,然后把该位置的值变为a[i]^x,相当于进行了一次a[i]^x的操作,这样总体看来就相当于进行了一次x^x

的操作,即剩下的就满足先手必输了,即所有值异或和为0,而该位置取得数目就是a[i]-(a[i]^x)。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10000005;
const int inf = 0x3f3f3f3f;
int n;
int a[maxn];
int main() {
    scanf("%d", &n);
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%d", a + i);
        ans ^= a[i];
    }
    if (ans == 0) {//无法获胜
        printf("lose\n"); return 0;
    }
    for (int i = 1; i <= n; i++) {
        if ((ans^a[i])<a[i]) {
        //ans^a[i] a[i]改为ans^a[i]
            printf("%d %d\n", a[i] - (a[i] ^ ans), i);
            a[i] = ans ^ a[i];
            for (int i = 1; i <= n; i++) {
                printf("%d", a[i]);
                if (i != n)printf(" ");
            }
            return 0;
        }
    }
    return 0;
}

 

posted @ 2021-04-27 19:05  cono奇犽哒  阅读(150)  评论(0)    收藏  举报