Codeforces Round #717 (Div. 2)-B. AGAGA XOOORRR-题解

Codeforces Round #717 (Div. 2)-B. AGAGA XOOORRR

传送门
Time Limit: 1 second
Memory Limit: 256 megabytes

Problem Description

Baby Ehab is known for his love for a certain operation. He has an array a a a of length n n n, and he decided to keep doing the following operation on it:

Now he asks you if he can make all elements of the array equal. Since babies like to make your life harder, he requires that you leave at least 2 2 2 elements remaining.

Input

The first line contains an integer t t t ( 1 ≤ t ≤ 15 1 \le t \le 15 1t15) — the number of test cases you need to solve.

The first line of each test case contains an integers n n n ( 2 ≤ n ≤ 2000 2 \le n \le 2000 2n2000) — the number of elements in the array a a a.

The second line contains n n n space-separated integers a 1 a_1 a1, a 2 a_2 a2, … \ldots , a n a_{n} an ( 0 ≤ a i < 2 30 0 \le a_i < 2^{30} 0ai<230) — the elements of the array a a a.

Output

If Baby Ehab can make all elements equal while leaving at least 2 2 2 elements standing, print “YES”. Otherwise, print “NO”.

Sample Input

2
3
0 2 2
4
2 3 1 10

Sample Onput

YES
NO

Note

In the first sample, he can remove the first 2 2 2 elements, 0 0 0 and 2 2 2, and replace them by 0 ⊕ 2 = 2 0 \oplus 2=2 02=2. The array will be [ 2 , 2 ] [2,2] [2,2], so all the elements are equal.

In the second sample, there’s no way to make all the elements equal.


题目大意

给你 n n n个数,你可以选择其中的任意两个进行异或操作,这样两个数就变成了一个数。
问你能不能使这 n n n个数最终的异或结果为不少于 2 2 2个的相同的数。


解题思路

首先要明白几个数相互异或,不论顺序如何,最终结果是不受影响的。
同时,两个相同的数异或结果是 0 0 0
我们可以先让所有的这 n n n个数全部异或,得到一个结果。


如果这个结果是 0 0 0,就说明得到 0 0 0这个结果的上一步是两个相同的数,即,只有两个相同的数异或才能得到 0 0 0。这样就说明可以找到一种异或顺序,使得最终异或结果是两个相等的数。就直接输出YES即可。


否则,如果结果想要是YES,就必须至少能异或成 3 3 3个相同的数(题目说了不能是 1 1 1个相同的数)。
3 3 3个相同的数异或得到的结果就是所有数异或得到的结果。
于是我们就从头开始异或,直到得到这个最终的异或结果,这就得到了三个数中的一个数。从下一个数开始逐个异或,知道可以再得到一个与最终结果相同的数为止,我们就得到了三个数中的第二个。剩下的数全部异或起来一定是结果这个数。这样的话就输出YES

如果有同学想问为什么输出YES的话,最终结果一定可以是 2 2 2个或 3 3 3个相同的数,而不是 4 4 4个或 5 5 5个呢?那么请看下面:

假设最终我们能够得到 4 4 4个相同的数,那么我们把这 4 4 4个相同的数分成两组,一组有两个数。则每组的两个数异或,原本的 4 4 4个数就变成了异或后的 2 2 2组。所以如果能最终能得到 4 4 4个相同的数,就一定能得到 2 2 2个相同的数。


同理,如果能分成 5 5 5组,就选其中的 3 3 3个数相异或变成一个数,就得到了相同的 3 3 3个数。所以如果最终能得到 5 5 5个相同的数,就一定能得到 3 3 3个相同的数。

如果还不太懂可以看看代码:


AC代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int a[2020];
void solve()
{
    int n;
    cin>>n;
    int res=0;//所有的数全部异或起来,最终结果是res
    fi(i,0,n)//for(int i=0;i<n;i++)
    {
        cd(a[i]);//scanf("%d", &a[i]);
        res^=a[i];//res异或上a[i]
    }
    if(res==0)//如果最终结果是0,那么得到0的上一步一定是两个相同的数
    {
        puts("YES");//所以我们可以直接输出YES并退出
        return;
    }
    int s=0;//一些数异或起来得到的结果
    int loc=0;//下标从第一个数开始
    for(loc=0;loc<n;loc++)
    {
        s^=a[loc];//异或上a[i]
        if(s==res)break;//如果前面一些数异或得到的结果已经是最终答案了,就找到了这3个数中的一个,就退出。
    }
    if(loc>=n-2)//如果不能再找到两个相同的数
    {
        puts("NO");//输出NO
        return;
    }
    loc++;//下标从下一个未异或过的数开始
    s=0;//一串异或起来的结果
    for(;loc<n-1;loc++)
    {
        s^=a[loc];//异或上a[loc]
        if(s==res)break;//如果结果是最终结果,就找到了第二个数
    }
    if(s!=res)//如果这一串异或起来不是最终结果
    {
        puts("NO");//就不行
        return;
    }
    loc++;//从下一个数开始异或
    s=0;//第三串异或的结果
    for(;loc<n;loc++)//这次要异或到最后
    {
        s^=a[loc];//异或上a[loc]
    }
    if(s==res)//如果第3串异或的结果也是最终结果
        puts("YES");//可以
    else//否则
        puts("NO");//不行
    return;    
}
int main()
{
    int N;
    cin>>N;//N组测试样例
    while(N--)
    {
        solve();
    }
    return 0;
}

如果哪里看不懂可以在下面评论留言

原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/116354549

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tisfy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值