洛谷9月月赛--T2[T2]预生成密码-这题还行

这是一道十分靠智商的题

(如果不想深入分析的话,这也是一道打打表找规律就能过的题


链接: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值