这是一道十分靠智商的题
(如果不想深入分析的话,这也是一道打打表找规律就能过的题
链接:https://www.luogu.org/problem/show?pid=T2
话说这题居然没有题号= =
题目大意:
你需要求出三个数字。
我们会给你三个数字的与,或,和。
当有多组解满足题意时,输出最小的数字最小的那个,当最小的数字相同时,输出次小的数字最小的那个。
有多组数据,所给三个数字均不超过10e18。
输入样例#1:
16 31 72
8 30 52
输出样例#1:
16 25 31
8 14 30
分析
我们发现,如果有解的话,那么最小的数字一定是”与”起来的数字,最大的数字一定是”或”起来的数字
为什么?
比如说下面这组数据:
5 127 259
他有多组解,我们取其中两组解:
最小的那组:5 127 127
中间的某组:39 95 125
我们将其二进制形式写出来:
39
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1
95
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1
125
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 1
我们发现,这并不是一组最小的解。因为解的三个数都需要包括”与”的所有二进制位之外,其余的二进制位,一定(只有一些数字含有),那我们明显可以把这些二进制位向较大数字放。
比如说:39,95,125他们都包含了”5”的二进制位
但是(第六个二进制位)只出现了两次,在39和125中出现,而95没有。那么我们明显可以把39里(第六个二进制位)放到95里,将其变成:
7
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
127
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
这样较小的数字就更小了,比我们更改之前的解更优,同理,我们把(第二个二进制位)也从7里面挪动到125里面,这样还会更优。
这样,我们就可以得到上述结论。
有解->有最优解证明完毕
但是如果没有解怎么办(题目不存在这种情况)
可以发现,我们把sum先减去”或”起来的值,再减去”与”起来的值,结果一定是中间那个数(最大和最小都被剪掉了)
再用所得结果减去”与”的值,得到的应该是中间那个数减去共有部分”与”
这样操作得到的这个数,我们设为X
如果说X&”与”的值,不为0,就无解
如果有解,因为X应该是中间那个数减去了共有部分之后剩下的数,这时候它和原来的共有部分进行”与“操作,明显结果应为0。
至此
!有最优解->!有解
即无最优解->无解证明那个完毕
贴代码:
//由于题目数据一定有解,故不用判定无解情况
#include <stdio.h>
long long A , B , C ;
int main(){
while( scanf( "%lld%lld%lld" , &A , &B , &C ) != EOF )
printf( "%lld %lld %lld\n" , A , C-A-B , B ) ;
return 0;
}