题解:P13683 【MX-X16-T1】「DLESS-3」XOR and Greater Sum

· · 题解

题目大意 小H有一个数字序列,他想选一些数字出来,让这些数字的"异或和"比剩下的数字的"异或和"大。问你能不能做到?

什么是异或和? 异或和就是把数字用"异或"(⊕)运算连起来的结果。比如:

1⊕1 = 0

1⊕2 = 3

4⊕5⊕1 = 0

解题关键 总异或和:先把所有数字异或起来,得到一个总数ans

神奇发现:

如果ans=0:怎么选都相等,肯定不行

如果ans≠0:找到ans的最高位(最左边的1)

必胜策略:

只要有一个数字在这个最高位是1,选它就赢了!

因为这样选出来的数肯定比剩下的大

举个栗子 比如数字:1,9,1,9,8,1,0

总异或和:1⊕9⊕1⊕9⊕8⊕1⊕0 = 9(二进制1001)

最高位是第3位(从右往左数,从0开始)

检查哪些数字第3位是1:

9(1001)是

8(1000)是

随便选一个(比如选9),它的异或和是9,剩下的异或和是0,9>0,成功!

为什么这样对? 选中的数字在最高位是1,所以它肯定比剩下的大

因为剩下的数字在这一位都是0(不然total这位不会是1)

代码实现 算ans

找最高位

检查有没有数字在这一位是1

有就Yes,没有就No

小技巧 用ans>>k &1可以检查某一位是不是1

用循环右移可以找到最高位 现在附上AC代码:

#include<bits/stdc++.h>  // 万能头不解释 
using namespace std;

int main() 
{
    int T;
    cin >> T;  // 输入不解释
    while(T--)  // n组数据 
    {
        int n;  // 定义数组长度
        cin>>n;  // 输入不解释 
        vector<int> a(n);  // 定义数组
        int ans = 0;  // 初始化异或和为0

        // 输入数组元素并计算总异或和
        for (int i=0;i<n;i++) 
        {
            cin>>a[i];  // 输入数组元素
            ans^=a[i];  // 计算异或和
        }

        // 如果总异或和为0,直接输出No
        if (ans==0) 
        {
            cout<<"No\n";
            continue;  // 跳过后续处理
        }

        int sum=0;  // 用于计算最高位位置
        int anss= ns;  // 复制异或和用于计算

        // 计算异或和的最高位位置
        while(anss!=0) 
        {
            anss>>=1;  // 右移一位
            sum++;  // 位数计数
        }
        sum--;  // 调整位数计数(从0开始)
        bool f=false;  // 标记是否存在最高位为1的元素

        // 检查数组中是否存在最高位为1的元素
        for (int i=0;i<n;i++) 
        {
            if ((a[i]>>sum)&1)  // 判断当前元素的最高位是否为1
            {
                f=true;  // 找到符合条件的元素
                break;  // 提前结束循环
            }
        }

        // 根据标记输出结果
        if(f) 
        {
            cout << "Yes\n";  // 存在满足条件的子集
        } 
        else 
        {
            cout << "No\n";  // 不存在满足条件的子集
        }
    }
    return 0;  // 程序正常结束
}

这样想是不是简单多啦!审核员大大通过一下吧,我的第一篇题解,感谢感谢