第十二届蓝桥杯Java省赛A组试题:异或数列

简介: 第十二届蓝桥杯Java省赛A组试题:异或数列

【题目描述】

初始时,Alice和Bob分别有一个整数a和b,有一个给定的长度为n的数列。a和b的初始值均为0。Alice和Bob轮流操作,Alice先手,每步可以从两个选项中选一种:

选项1:从数列中选一个X;给Alice的数异或上。

选项2:从数列中选一个X;给Bob的数异或上。

每个数Xi只能用一次,当每个数都被用过一遍后,游戏结束。拥有数大的一方获胜,双方数字相同即平局。

双方都足够聪明,都采用最优策略,问谁能获胜?


【输入格式】

每个评测用例包含多组询问。询问之间彼此独立。

输入的第一行包含一个整数T,表示询问数。

接下来T行每行包含一组询问。其中第i行的第一个整数n;表示数列长度,随后n个整数X1, X2,… Xm表示数列中的每个数。


【输出格式】

输出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


【评测用例规模与约定】

对于所有评测用例,1 ≤ T ≤ 200000,1 ≤ ∑Ti=1 ni ≤ 200000,0 ≤ Xi < 220。


【解题思路】

借鉴:该博客


首先明确,为什么给定一个数列,游戏的结局是确定的呢?

A赢的意思是:A能采取某种策略,不管B作何应对,A保证自己一定能赢;

B赢的意思是:B能采取某种策略,不管A作何应对,B保证自己一定能赢;

对于异或:0^X ——保持X ; 1^X——翻转X;

偶数次翻转将回到原来的状态,即与偶数个1异或将保持不变。


最后两个结果数A^B = a^b^sum ,其中sum为给定数列所有数的异或和,sum = X1^X2^...Xni,所以如果是平局(即A = B),则A^B=0(即 sum = 0)。


现在考虑sum != 0时,因为是按位异或,并且最后比较A和B两值的大小,所以要从二进制的最高位开始比较,如果最高位相等,比较次高位,以此往下比较,直到可以判断出结果。


用一个int型数组res[i]表示二进制的第i位上1的个数,如果某一位的res[i]为奇数,即该位上有奇数个1与a和b异或,比如有5个1,因为0不会改变状态,其(a,b)的状态转移过程一定是:(0,0)->翻转->平局->翻转->平局->翻转,也就是说在平局不管是(0,0)或(1,1)的基础上,Alice 和 Bob谁拥有最后一次翻转权(也就是最后一个1),谁就赢得游戏!


那怎么让最后一个1轮到自己身上?就要用到0了,因为0不会改变数的大小,但相当于让自己“轮空一次”。还是考虑上面5个1的情况:如果在最后一次翻转之前(不管在什么位置)插入偶数个0,则最后一次1的翻转权来到了先手 Alice,则先手胜出;如果在最后一次翻转之前(不管在什么位置)插入奇数个0,则最后一次1的翻转权来到了后手 Bob,则后手胜出。


因为Alice和Bob都“足够聪明”,面对奇数个1,Bob一定要去“ 抢0 ”,自己才有一线生机,而Alice也要以“ 抢0 ”来作应对,让最后一次翻转权回到自己手里,因为0的个数有限,最后决定胜负的就是0个数的奇偶性。


因此,如果某一位的res[i]为偶数,则游戏结果的这一位一定相等,考虑下一位 ;如果第i位上1的个数为 1,则一定是先手赢(输出:“1”);如果第i位上1的个数为大于1的奇数,0的个数为偶数,则先手赢(输出:“1”);如果第i位上1的个数为大于1的奇数,0的个数为奇数,则后手赢(输出:“-1”)。


Java代码:


import java.util.ArrayList;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        //该ArrayList用来暂存每次询问结果,待最后一次询问结束再统一输出
        ArrayList<Integer> res = new ArrayList<>();
        //n次询问
        for (int i = 0; i < n; i++) {
            int[] weis = new int[24]; //该数组用于存储二进制形式下每一位1的数量
            int m = scanner.nextInt();
            //长度为m的数列转为二进制并处理
            for (int j = 0; j < m; j++) {
                long l = scanner.nextLong();
                String string = Long.toBinaryString(l); //转为二进制
                String reStr = new StringBuilder(string).reverse().toString(); //反转,即高低位反转,便于存储与后面处理
                //判断二进制形式下每一位是否为1
                for (int k = 0; k < reStr.length(); k++) {
                    if (reStr.charAt(k) == '1') weis[k]++;
                }
            }
            //对每次询问后每一位中1的个数判断从而得到结果,并将结果先暂时存储在ArrayList-res中
            for (int j = weis.length - 1; j >= 0; j--) {
                if (weis[j] % 2 == 0 && j == 0) {
                    res.add(0);
                    break;
                }else if (weis[j] % 2 == 0){
                    continue;
                }
                if (weis[j] == 1){
                    res.add(1);
                    break;
                }else if (weis[j] % 2 == 1 && (m - weis[j]) % 2 == 0){
                    res.add(1);
                    break;
                }else if (weis[j] % 2 == 1 && (m - weis[j]) % 2 == 1){
                    res.add(-1);
                    break;
                }
            }
        }
        //输出结果
        for (int x : res){
            System.out.println(x);
        }
    }
}


相关文章
|
1月前
|
人工智能 Python
蓝桥杯练习题(四):Python组之历届试题三十题
关于蓝桥杯Python组历届试题的三十个练习题的总结,包括题目描述、输入输出格式、样例输入输出以及部分题目的解题思路和代码实现。
28 0
蓝桥杯练习题(四):Python组之历届试题三十题
|
5月前
|
Java
2016届蓝桥杯大赛软件类国赛Java大学B组 愤怒小鸟 数学模拟
2016届蓝桥杯大赛软件类国赛Java大学B组 愤怒小鸟 数学模拟
48 4
|
5月前
|
Java
2022蓝桥杯大赛软件类国赛Java大学B组 左移右移 空间换时间+双指针
2022蓝桥杯大赛软件类国赛Java大学B组 左移右移 空间换时间+双指针
42 3
|
5月前
|
Java
2021蓝桥杯大赛软件类国赛Java大学B组 完全日期 复杂遍历搜索
2021蓝桥杯大赛软件类国赛Java大学B组 完全日期 复杂遍历搜索
49 2
|
5月前
|
Java
2023届蓝桥杯大赛软件类国赛Java大学B组 互质 数论
2023届蓝桥杯大赛软件类国赛Java大学B组 互质 数论
37 1
|
5月前
|
存储 前端开发 算法
2016届蓝桥杯大赛软件类国赛Java大学B组 反幻方 暴力搜索
2016届蓝桥杯大赛软件类国赛Java大学B组 反幻方 暴力搜索
31 0
|
6月前
|
人工智能 算法 Java
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-992 士兵杀敌(二)
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-992 士兵杀敌(二)
79 1
|
6月前
|
人工智能 算法 Java
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1005 数字游戏
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1005 数字游戏
106 0
|
6月前
|
Java C语言 C++
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1000 kAc给糖果你吃
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-1000 kAc给糖果你吃
82 0
|
6月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-999 数的潜能
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-999 数的潜能
82 0