CodeForces - 1325D Ehab the Xorcist(构造+思维)

题目链接:点击查看

题目大意:给出一个 u 和一个 v ,要求构造出最短的一个数组,使得

  1. 所有元素异或的结果为 u 
  2. 所有元素之和的结果为 v

输出构造的结果

题目分析:情况稍微比较复杂的一道构造题,读完题后,先根据样例特判,当 u 和 v 为 0 时,答案为 0 ,当 u 和 v 相等时,答案为 u,当 u > v 时,答案为 -1,这些根据样例的提示应该不难想

接下来我们应该构造通项,根据异或的性质, u xor u = 0,加上经过上面的筛选之后,我们可以构造一个长度为 3 的数组,其值分别为 x y y ,令 x = u ,显然满足 x ^ y ^ y = u ,现在只需要满足 u + y + y = v 就好了,解方程得到 y = ( v - u ) / 2 ,所以这里必须满足 v - u 可以被 2 整除才行,如果不能被整除那么答案就是 -1 了,到此为止所有的特判都已经完成了,但是根据样例的提示,我们发现答案会有长度为 2 的数组,这个该怎么办呢,其实经过上面的分析,我们可以发现,长度为 2 的数组其实就是 x y y 合并成了 x + y , y 了而已,这也就启发了我们的思路,我们接下来的问题就转换为了分析出什么时候可以将 x y y 合并成 x + y  y ,因为加法运算满足结合律,x + y + y 和 ( x + y ) + y 是等价的,所以我们只需要考虑什么时候 x ^ y ^ y = ( x + y ) ^ y ,同时约分掉 y 后,可以得到当 x ^ y = x + y 时满足三项可以合并为两项,到这里应该不难猜出,当且仅当 x & y == 0 时,三项可以合并为两项了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
      
typedef long long LL;

typedef unsigned long long ull;
      
const int inf=0x3f3f3f3f;
 
const int N=1e4+100;

int main()
{
#ifndef ONLINE_JUDGE
//    freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
#endif
//    ios::sync_with_stdio(false);
	LL u,v,w;
	scanf("%lld%lld",&u,&v);
	if(u>v||(u-v)%2)
		return 0*printf("-1\n");
	if(u==0&&v==0)
		return 0*printf("0\n");
	if(u==v)
		return 0*printf("1\n%lld\n",v);
	w=(v-u)/2;
	if((u&w)==0)
		return 0*printf("2\n%lld %lld\n",w,w+u);
	printf("3\n%lld %lld %lld\n",u,w,w);
	
    
    
    
    
    
    
    
    
    
    
    
    
    return 0;
}
发布了691 篇原创文章 · 获赞 27 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104872542