CodeForces - 1270C Make Good(思维+构造)

题目链接:点击查看

题目大意:给出一个由n个数字构成的数列,现在已知其累加和为sum,异或和为xor,现在允许我们向数列中添加0~3个数,以满足sum=2*xor,构造出任意一种方案

题目分析:一开始我想分情况讨论的,就是在求出sum和xor之后,讨论一下其大小关系,如果sum小于2*xor的话,直接补齐两个其差值的一半就好了,因为新补的两个数对xor不做贡献,而对sum的贡献就是差值,可以满足条件了,不过需要对奇偶讨论一下,因为奇数的一半会出现小数,这个时候我们就可以用第三个数来补齐一下了,也就是先让sum加一,再让xor异或1,这个时候其差值就是偶数了,剩下的就是当sum大于2*xor的时候,这个时候我考虑到首先加上一个数,让其回到第一种情况即可,不过这样想下来构造所需要处理的细节就太多太多了。。很不可取,即使勉强写出来了也耗费了不少时间,而且应该很难1A

这个时候我们就可以直接从公式出发,先将数字抽象出来,在输入完成后我们只有sum和xor两个数值,若想满足sum=xor*2,因为不可控因素较多,我们不妨先把xor给消掉,也就是添加一个数,令其权值等于xor,这样等式就变成了sum+xor=2*(xor^xor),也就是sum+xor=0,这有个什么好处呢,这个公式的等式右边,也就是需要异或的地方变成了零,接下来我们无论添加的数为多少,会造成的贡献就是等式两边都加上相同的数值,因为我们需要维持两倍的关系,所以完全可以添加一个sum+xor,这样等式两边就可以符合题意了

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
    
typedef long long LL;
    
const int inf=0x3f3f3f3f;

const int N=1e5+100;

int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);
	int w;
	cin>>w;
	while(w--)
	{
		int n;
		scanf("%d",&n);
		LL sum=0,_xor=0;
		for(int i=1;i<=n;i++)
		{
			LL num;
			scanf("%lld",&num);
			sum+=num;
			_xor^=num;
		}
		printf("2\n");
		printf("%lld %lld\n",_xor,_xor+sum);
	}
	
	
    
    
    
    
    
    
 
        
        
        
         
        
    return 0;
}

 

你可能感兴趣的:(思维,构造,异或和)