如果a1+a2+⋯+am=2⋅(a1⊕a2⊕⋯⊕am),我们称非负整数的数组a1,a2,...,am为好,其中⊕表示比特XOR操作。
例如,数组[1,2,3,6]是好的,因为1+2+3+6=12=2⋅6=2⋅(1⊕2⊕3⊕6)。同时,数组[1,2,1,3]并不好,因为1+2+1+3=7≠2⋅1=2⋅(1⊕2⊕1⊕3)。
给你一个长度为n的数组:a1,a2,...,an。最多添加3个元素,使之成为良好的数组。附加的元素不一定要不同。可以证明,在给定的约束条件下,解决方案总是存在的。如果有不同的解决方案,你可以输出其中任何一个。请注意,你不一定要使添加元素的数量最小化!。所以,如果一个数组已经很好,你可以不添加元素。
输入
每个测试包含多个测试案例。第一行包含测试用例的数量t(1≤t≤10000)。测试用例的描述如下。
每个测试用例的第一行包含一个整数n (1≤n≤105) - 阵列的大小。
每个测试案例的第二行包含n个整数a1,a2,...,an(0≤ai≤109)--数组的元素。
保证所有测试用例的n之和不超过105。
输出
对于每个测试案例,输出两行。
在第一行,输出一个整数s (0≤s≤3) - 你想追加的元素的数量。
在第二行,输出s个整数b1,...,bs (0≤bi≤1018) - 你想追加到数组的元素。
如果有不同的解决方案,你可以输出其中任何一个。
例子
InputCopy
3
4
1 2 3 6
1
8
2
1 1
输出拷贝
0
2
4 4
3
2 6 2
注意
在例子的第一个测试案例中,所有数字的总和是12,它们的⊕是6,所以条件已经满足。
在例子的第二个测试案例中,在加上4,4之后,数组变成了[8,4,4]。其中的数字之和为16,其中的数字的⊕为8。
根据异或的概念x异或x为0
两种思路(想复杂了)
第一种构建一个很大数a
s1+=a s2^=a;相当于s1与s2都加上了这个数
因为答案s1要等于s2的二倍我们可以加上两个(s2*2-s1)*2;而两个相同的数异或为0
#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll n;
scanf("%lld",&n);
ll s1 = 0,s2 = 0;
for(int i = 1; i <= n; i++)
{
ll x;
scanf("%lld",&x);
s1 += x;
s2 ^= x;
}
if(s1 == s2*2)
{
printf("0\n\n");
continue;
}
long long a = (1LL<<50);
a += s1%2;
s1 += a;
s2 ^= a;
ll ans = (s2*2 - s1)/2;
printf("3\n%lld %lld %lld\n",a,ans,ans);
}
}
第二种思路(简单)
直接利用数本身s1 加上 (s2) 和(s1+s2)
s2异或(s2)和(s1+s2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;
const int N = 1e5+10;
#define ios \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0);
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
ll xo=0,sum=0;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
xo^=x;
sum+=x;
}
cout<<2<<endl;
cout<<xo<<" "<<sum+xo<<endl;
}
}