题意:
给定两个数,u,v;
要求你输出一个最短的数组,
先输出数组的长度,再输出各个元素。
这个数组要求所有元素异或和为u,
所有元素数字之和为v
比如:
a⊕b⊕c=u , a+b+c=v;
比赛思路:
能有什么思路? 我就满脸懵逼啊
一直看着题目,希望可以从中看出一些端倪;
结果还是不知道 到底应该如何入手这题,我寻思也没有什么用法可以完成这个重任啊。。。
题解:
#include <stdio.h>
int main() {
long long u, v, w;
scanf("%lld%lld", &u, &v);
if (u > v || (v - u) % 2 != 0) {
printf("-1\n");
return 0;
}
if (u == 0 && v == 0) {
printf("0\n");
return 0;
}
if (u == v) {
printf("1\n");
printf("%lld\n", u);
return 0;
}
w = (v - u) / 2;
if ((u & w) == 0) {
printf("2\n");
printf("%lld %lld\n", w, u ^ w);
return 0;
}
printf("3\n");
printf("%lld %lld %lld\n", u, w, w);
return 0;
}
搬了榜最前的一个大佬的代码,
写得很清晰;也感谢群里大佬的解答
解题思路:
一,
要注意好细节,
这给的u,v首先就很大 先开longlong
然后就是分类挺多的,要考虑周全,不然就要wa个好几次
二,
要知道这么一个概念
一个数异或两次另一个数,结果还是等于自身;
换成公式来说就是 u = u ⊕ t ⊕ t;
ps:这个是可以推出来的,但是要记住比较好。
由此我们就只要 让 v = u + t + t 。
这样的话,题目的两个条件就都满足啦。
三,
但是如何让这个数组的长度更短呢?
这里还要知道一个概念,
两个数,比如数a,b。
如果他们的每一位都不同时为1的话,
那么这两个数 a + b = a ⊕ b;
这也是可以推理得出来的,
0⊕1=1 , 1⊕0=1 , 0⊕0=0 这三个异或的结果都是与加法的结果一样的,当然如果是1⊕1的话 虽然 无论是异或 还是 加法 都是变成0,但是加法里还要进位,所以当有一位同时为 1 时,a + b = a ⊕ b就不满足了。
知道了这个概念以后,我们就可以把数组缩短成 u+t 和 t 这两个元素了。
只要加一层判断,判断是否 u&w==0,如果有某位同时为1的话,那肯定就不为0,就不走这层过了。
所以只要满足u & w == 0,那么直接输出2,以及这两个元素,
四,
我们还要注意什么?
① 如果给的 u , v
1)u>v时,那肯定找不到这样的数组,输出-1;
2)u,v的奇偶不同的话,也要输出-1;为何?
因为首先 t+t 之和肯定是偶,那如果u为奇,则v肯定为奇;
如果u为偶,那v也肯定为偶;
所以当u,v奇偶不同时,肯定找不到符合的数组,直接输出-1
② 如果u和v同时为0的话,直接输出0
③ 如果u和v同时为1的话,输出1,输出u或v
感觉这几个坑点蛮恶心的。