题解: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; // 程序正常结束
}
这样想是不是简单多啦!审核员大大通过一下吧,我的第一篇题解,感谢感谢