LQ0111 异或数列博弈

Posted 海岛Blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LQ0111 异或数列博弈相关的知识,希望对你有一定的参考价值。

题目来源:蓝桥杯2021初赛 C++ A组G题

题目描述
Alice 和Bob 正在玩一个异或数列的游戏。
初始时,Alice 和Bob 分别有一个整数a 和b,初始值为0。
有一个给定的长度为n 的公共数列X1, X2, … , Xn。
Alice 和Bob 轮流操作,Alice 先手,每步可以在以下两种选项中选一种:
选项1:从数列中选一个Xi 给Alice 的数异或上,或者说令a 变为a ⊕ Xi。(其中⊕ 表示按位异或)
选项2:从数列中选一个Xi 给Bob 的数异或上,或者说令b 变为b ⊕ Xi。
每个数Xi 都只能用一次,当所有Xi 均被使用后(n 轮后)游戏结束。
游戏结束时,拥有的数比较大的一方获胜,如果双方数值相同,即为平手。
现在双方都足够聪明,都采用最优策略,请问谁能获胜?

输入格式
每个评测用例包含多组询问。询问之间彼此独立。
输入的第一行包含一个整数T,表示询问数。
接下来T 行每行包含一组询问。
其中第i 行的第一个整数ni 表示数列长度,随后ni 个整数X1, X2, … , Xni 表示数列中的每个数。
1 ≤ T ≤ 200000, 1 ≤ sum(ni) ≤ 200000, 0 ≤ Xi < 2^20

输出格式
输出T 行,依次对应每组询问的答案。
每行包含一个整数1、0 或-1 分别表示Alice 胜、平局或败。

输入样例
4
1 1
1 0
2 2 1
7 992438 1006399 781139 985280 4729 872779 563580

输出样例
1
0
1
1

问题分析
(略)

AC的C语言程序如下:

/* LQ0111 异或数列 */

#include <stdio.h>

#define N 200000
int a[N];

int judge(int cnt1, int cnt2)

    if (cnt1 % 2 == 0) return 0;
    if (cnt1 == 1) return 1;
    if (cnt1 % 2 != 0 && cnt2 % 2 != 0) return -1;
    else return 1;


int main()

    int t, n;
    scanf("%d", &t);
    while (t--) 
        int sum = 0;
        scanf("%d", &n);
        for (int i = 0; i < n; i++) 
            scanf("%d", &a[i]);
            sum ^= a[i];
        

        if (sum == 0) 
            printf("0\\n");
            continue;
        
        for (int i = 20; i >= 0; i--) 
            int cnt1 = 0, cnt2 = 0;
            for (int j = 0; j < n; j++)
                if ((a[j] >> i) & 1) cnt1++;
                else cnt2++;
            int t = judge(cnt1, cnt2);
            if ( t == 0)
                continue;
            else 
                printf("%d\\n", t);
                break;
            
        
    

    return 0;

以上是关于LQ0111 异或数列博弈的主要内容,如果未能解决你的问题,请参考以下文章

2017EC Final L SOS——找规律&&博弈

BZOJ3759: Hungergame 博弈论+线性基

(HDU - 2176)取(m堆)石子游戏(尼姆博弈)

BZOJ.1022.[SHOI2008]小约翰的游戏John(博弈论 Anti-Nim)

尼姆博弈

Tokitsukaze and Duel CodeForces - 1191E (博弈论)