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

82 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

@TOC

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 aa of length nn, 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 22 elements remaining.

Input

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

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

The second line contains nn space-separated integers a1a_1, a2a_2, \ldots, ana_{n} (0ai<2300 \le a_i < 2^{30}) — the elements of the array aa.

Output

If Baby Ehab can make all elements equal while leaving at least 22 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 22 elements, 00 and 22, and replace them by 02=20 \oplus 2=2. The array will be [2,2][2,2], so all the elements are equal.

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


题目大意

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


解题思路

首先要明白几个数相互异或,不论顺序如何,最终结果是不受影响的。 同时,两个相同的数异或结果是00。 我们可以先让所有的这nn个数全部异或,得到一个结果。
如果这个结果是00,就说明得到00这个结果的上一步是两个相同的数,即,只有两个相同的数异或才能得到00。这样就说明可以找到一种异或顺序,使得最终异或结果是两个相等的数。就直接输出YES即可。
否则,如果结果想要是YES,就必须至少能异或成33个相同的数(题目说了不能是11个相同的数)。 这33个相同的数异或得到的结果就是所有数异或得到的结果。 于是我们就从头开始异或,直到得到这个最终的异或结果,这就得到了三个数中的一个数。从下一个数开始逐个异或,知道可以再得到一个与最终结果相同的数为止,我们就得到了三个数中的第二个。剩下的数全部异或起来一定是结果这个数。这样的话就输出YES

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

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

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


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;
}

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

同步发文于我的CSDN,原创不易,转载请附上原文链接哦~
Tisfy:letmefly.blog.csdn.net/article/det…