首先我们要知道一个知识
加法运算的位运算表示
x+y = x^y+2*x&y
x^y
算出的是x和y之间位相加但不进位的结果
2*x&y
算出的是x和y之间的有进位的对应位
eg:
110和110
我们在第3位和第2位都有进位
但是实际上我们是要进位到第4位和第3位
所以我们还要对x&y
的结果向左做移位运算,也就是2*x&y
好了现在我们知道了加法运算的位运算表示,我们可以开始推导一些式子了
如非退化三角形要求的x+y>x^y
我们可以看成是x^y+2*x&y>x^y
即可推导出x&y>0
所以x和y之间至少有一位是需要相同的
继续由退化三角形我们还有y+x^y>x
y+x+y-2*x&y>x
所以有
y>x&y
所以我们还得知了y中至少包含一个x中为打开的位(x有一位为0,而这位在y中为1)
所以我们便将问题转化为了寻找一个数,它的某一位是1,而x中为0,它的某一位为1,且x中也为1
所以我们便可以暴力枚举所有只有两位是1的数,判断它是否和x满足非退化三角形的关系
注:为什么没考虑x+x^y>y(因为x>y,x&y>=0,所以这是显然的hh~)
在没有判断非退化三角形前x&y的取值范围为>=0
借鉴了官方题解的代码
有没有更好的做法???
#include <iostream>
using namespace std;int main(){int t;cin>>t;while(t--){int x;cin>>x;int ans = -1;for(int i=0;i<=30;i++) for(int j=0;j<=30;j++){int y = (1<<i|1<<j);if(y<x&&x+y>(x^y)&&y+(x^y)>x){ans = y;}}cout<<ans<<endl;}return 0;}
附:
//位运算实现加法的代码
#include <iostream>
using namespace std;int main(){int a,b;cin>>a>>b;int t = int(a^b)+(int(a&b)<<1);cout<<t<<endl;return 0;}