zoukankan      html  css  js  c++  java
  • Codeforces 1325D

    题意:

    给定两个数 u v ,求一个最短的数组

    这个数组所有元素按位异或等于 u ,且和为 v

    找不到输出 -1

    否则输出数组的个数,再输出数组内的正整数

    解题思路:

    首先考虑到 -1的情况

      根据二进制关系,

      一个数    异或=和(自己=自己)

      两个及以上数    异或<=和(二进制加法得知,等于的情况出现在多个数的二进制中 1 的位都不相同时)

      所以按位异或得出的结果一定不会比被异或的数之和更大

      然后对于奇偶判断,如果异或值为奇数,说明被异或的数中一定有奇数个奇数,才会导致最低位为 1

      而奇数个奇数与不论多少个偶数相加,和一定也是奇数

      所以异或值与和的奇偶性一定相同

    排除不可能的答案后,接下来就是找答案

    首先,数组内一定要是正整数

    所以考虑 u=v=0 的特殊情况,直接输出一个 0 (见样例)

    然后,如果 u=v≠0 ,直接输出个数为1,数值为u的特殊答案

    然后我们可以发现,最直接的答案就是三个数字,其中两个数字相同,另外一个数字为异或的值 u

    此时三个数就是 u    (v-u)/2    (v-u)/2

    因为相同的数字异或值为0,只需要让这三个数和为 v 即可

    但因为要求元素最少的数组,所以要考虑能否只用两个数字就满足题意

    会发现,如果 u 和 (v-u)/2 的二进制上的 1 不会在同一位同时出现

    此时异或运算会等同于二进制加法运算

    即 u^x^x = v

    此时把 u^x 看作一个数,x看作另一个数,异或运算变成加法运算后

    也就是 u+x 和 x 两个数,满足 (u+x)^x=u    u+x+x=v

    直接合并此时的 u+x 即可

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int main()
    {
        ll u,v,x,y;
        cin>>u>>v;
        if(u%2==v%2&&u<=v){
            if(u==v){
                if(!u)
                    cout<<"0
    ";
                else
                    cout<<"1
    "<<u<<'
    ';
            }
            else{
                x=u;
                y=(v-u)/2;
                if((x&y)==0)
                    cout<<"2
    "<<(x+y)<<' '<<y<<'
    ';
                else
                    cout<<"3
    "<<x<<' '<<y<<' '<<y<<'
    ';
            }
        }
        else
            cout<<"-1
    ";
        
        return 0;
    }
  • 相关阅读:
    多播委托和匿名方法再加上Lambda表达式
    委托
    从警察抓小偷看委托
    StringBuilder
    C#修饰符详解
    数据结构与算法之队列
    数据结构与算法之栈
    win10重复安装
    网络编程基础
    PrintPreviewControl
  • 原文地址:https://www.cnblogs.com/stelayuri/p/12495726.html
Copyright © 2011-2022 走看看