Make Good(思维+异或)

Problem - 1270C - Codeforces

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


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值