哈尔滨理工大学软件与微电子学院程序设计竞赛——D.Array【二进制 & 思维】(详解!思路以及严谨推导)

题目传送门


在这里插入图片描述


题解

  • u : v u:相加和,v:异或和
  • 在二进制运算中,对于某一位来讲:
    a b a + b a \wedge b:表示a+b的本位
    a   &   b : a + b a\ \&\ b:表示a+b应该进的位
  • 那么 a   &   b < < 1 a\ \&\ b <<1:表示进位之后
  • 所以 a + b = ( a b )   +   2 ( a   &   b ) a+b=(a \wedge b)\ +\ 2*(a\ \&\ b )
  • 同理,对于一个二进制运算也是一样的。
  • 带入本题: v = u + 2 ( a   &   b ) v=u+2*(a\ \&\ b)
  • 情况一: u > v     ( v u ) % 2 = = 1 u>v \ 或\ (v-u)\%2==1
    这两种情况都是不满足上面等式,属于非法输入,直接输出-1
  • 情况二: u = = v u==v
    1. v = = 0 v==0 ,这是空数组的情况,输出0
    2. v    ! = 0 v\ \ !=0 ,说明数组只有一个元素,输出 u \boldsymbol{u}
  • 接下来我们就需要认真分析了。
  • d = ( v u ) / 2 = a   &   b d=(v-u)/2=a\ \&\ b
  • 我们可以构造特殊数组,因为相同的两个数异或值等于0,所以可以构造出 u   0 = u u \wedge\ 0=u ,这个 0 0 是由两个 d d 组成的,也就是数组为 [ u , d , d ] \boldsymbol{[u,d,d]}
  • 我们来验证一下:
    u + d + d = u + ( v u ) = v u+d+d=u+(v-u)=v
    u d d = u u\wedge d\wedge d=u
    符合题意!也就是说,最多三个元素就可以满足题意。
  • 让我们继续思考能否继续缩减成 2 2 个元素 样例已经告诉我们了
  • 我们试着从当前答案进行转化,把其中一个 d d u u 合并。也就是 [ d , u + d ] [d,u+d]
  • 我们来验证一下:
    d + u + d = v d+u+d=v
    d ( u + d ) = ( ( v u ) / 2 ) ( u + ( v u ) / 2 ) = ( ( v u ) / 2 ) ( ( v + u ) / 2 ) d \wedge (u+d)=((v-u)/2) \wedge (u+(v-u)/2)=((v-u)/2) \wedge ((v+u)/2)
    【emmm,好像看不出什么】
  • 换个思路,我们知道 [ u , d , d ] \boldsymbol{[u,d,d]} 一定是对的,那么我们把 u , d u + d \boldsymbol{u,d}合并为一个 \boldsymbol{u+d} ,就是在找这种情况满足的条件。
  • 回顾通解: [ u , d , d ] \boldsymbol{[u,d,d]}
    u d d = u u\wedge d\wedge d=u
  • 再看特解
    d ( u + d ) =   ? d \wedge (u+d)=\ ?
  • 如果想要这两个式子等价,也就是特解,那么需要保证 u + d = = u d \boldsymbol{u+d==u \wedge d}
  • 至此,我们已经分析完了所有的情况。
  • 总结一下后两种情况:
  • 情况三: 通解 [ u , d , d ] \boldsymbol{[u,d,d]}
  • 情况四: u + d = = u d \boldsymbol{u+d==u \wedge d} 的时候,特解 [ u + d , d ] \boldsymbol{[u+d,d]}
  • 情况四的特解条件可以继续化简,步骤如下:
    因为 a + b = ( a b )   +   2 ( a   &   b ) a+b=(a \wedge b)\ +\ 2*(a\ \&\ b )
    带入 u d u和d u + d = ( u d )   +   2 ( u   &   d ) u+d=(u \wedge d)\ +\ 2*(u\ \&\ d )
    等价于 u   &   d = = 0 u\ \&\ d==0
  • 到这里,就没有什么其他的东西了,顺便说一下,这道题是 Codeforces 1325 D. Ehab the Xorcist原题

AC-Code

#include <bits/stdc++.h>
using namespace std;

int main() {
    int u, v;
    while(cin >> u >> v) {
        if(u > v || ((v - u) & 1)) {
            cout << -1 << endl;
            continue;
        }
        if(u == v) {
            if(v)
                cout << 1 << endl; // u;
            else
                cout << 0 << endl;
            continue;
        }
        int d = (v - u) / 2;
        if(d & u) {
            cout << 3 << endl; // u, d, d
        }
        else {
            cout << 2 << endl; // d, u+d
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Q_1849805767/article/details/106773661