zoukankan      html  css  js  c++  java
  • CF1325D Ehab the Xorcist

    传送门


    题意:让你构造最短的一个数组,满足所有元素的异或和为(u),和为(v).


    这题典型的cf题,思维难度挺大,然后代码量挺少。

    这题应该是充分地锻炼了我的位运算本领吧。

    首先要观察到这么个性质,就是(u)(v)必须奇偶相同(显然,二进制最低位1的奇偶性相同),那么如果(u > v),或(u,v)奇偶性不同,都输出-1.

    除以上情况外,令(x=frac{v-u}{2}),那么序列({u,x,x})必定是符合要求的(好妙啊,我咋就没想出来)。因此我们只要判断是否能由两个数构造出来,即(exist a, b, extrm{s.t.} a igoplus b = u, a + b = v).

    考虑到异或实际上就是不进位的加法,而利用按位与操作,我们能知道哪些位会进位,那么就有(a+b=a igoplus b + 2 * a extrm{&} b),因此(a & b = frac{a + b - a igoplus b}{2}=frac{v-u}{2}=x)(神奇吧)

    那么什么时候存在这样的(a,b)呢?有上面推论可知,(a& b=x, a igoplus b = u),那么当(x)某一位为1时,(u)这一位必须是0;而当(x)某一位为0时,(u)这一位随意。所以当(x & u = 0)时,(a,b)存在;否则答案只能是({u,x,x})

    (a,b)如何构造?会发现,当(x & u=0)时,(x+u=x igoplus u),因此构造({x+u,x})就行了!

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<queue>
    #include<assert.h>
    #include<ctime>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    //const int maxn = ;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
    	freopen(".in", "r", stdin);
    	freopen(".out", "w", stdout);
    #endif
    }
    
    int main()
    {
    //	MYFILE();
    	ll u = read(), v = read();
    	if(u > v || (u & 1) != (v & 1)) puts("-1");
    	else if(u == v)
    	{
    		if(u) printf("1
    %lld
    ", u);
    		else puts("0");
    	}
    	else
    	{
    		ll x = (v - u) >> 1;
    		if(x & u) printf("3
    %lld %lld %lld
    ", u, x, x);
    		else printf("2
    %lld %lld
    ", u + x, x);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Grunt学习笔记【7】---- grunt-contrib-less插件详解
    Grunt学习笔记【6】---- grunt-contrib-requirejs插件详解
    Grunt学习笔记【5】---- expand使用方法
    Grunt学习笔记【4】---- 通配符和模板
    Grunt学习笔记【3】---- filter使用方式和实现原理详解
    Grunt 学习笔记【2】---- 配置和创建任务
    用css去除chrome、safari等webikt内核浏览器对控件默认样式
    angular中通过$location获取路径(参数)的写法
    angular自身带有的操作cookie的方法
    js中apply方法的使用
  • 原文地址:https://www.cnblogs.com/mrclr/p/15349896.html
Copyright © 2011-2022 走看看