原题链接:
E. Vlad and a Pair of Numbers
题意:
题目有公式 a ⊕ b = ( a + b ) / 2 = x a ⊕ b = (a + b) / 2 = x a⊕b=(a+b)/2=x, 给你的是 x x x,让输出一组满足题目要求的 a , b a,b a,b,没有就输出 − 1 -1 −1。
解题:
首先分析异或的性质,不同为1,相同为0。所以可以把
x
x
x 给二进制化得到字符串s,在s是1的位置上
a
a
a 和
b
b
b 肯定一个是0,一个是1。不妨假定把所有的1都给
a
a
a ,然后去分析
(
a
+
b
)
/
2
(a + b) / 2
(a+b)/2,这就相当于把
a
+
b
a + b
a+b 右移一位,所以只要让
a
a
a 和
b
b
b 在 s 为1的位置的上一个地方变成1就可以了,如果下一个位置的地方也是1的话就无解,输出-1。证明如下:
我们不妨通过
x
x
x 来反推
a
+
b
a + b
a+b,可以得到一个 1 的位置永远都比
x
x
x 的 1 的位置要往前一位,所以要得到这个二进制数只要在的1的后一位的地方变成1就好了,这里要是不懂得话就找一个数推一下,下面是一个例子。
10进制 | 二进制 |
---|---|
x | 001010100 |
a | 001111110 |
b | 000101010 |
a + b | 010101000 |
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long LL;
const int N = 5e5 + 10, mod = 998244353;
void solve()
{
int n;
cin >> n;
int a = 0, b = 0;
if (n & 1) cout << -1 << '\n';
else
{
for (int i = 1; i <= 30; i ++ )
{
if (n >> i & 1)
{
if (n >> (i - 1) & 1)
{
cout << -1 << '\n';
return;
}
}
}
for (int i = 1; i <= 30; i ++ )
{
if (n >> i & 1)
{
a += 1 << i;
a += 1 << (i - 1);
b += 1 << (i - 1);
}
}
cout << a << ' ' << b << '\n';
}
}
signed main()
{
int T = 1;
cin >> T;
while (T -- )
{
solve();
}
return 0;
}