ようにAとBの整数を考えると、Xの整数を見つけます:
- A、B <2 * 1E18
- XOR X = B + X
私は非常に数学を使ってこの方程式を解くことが可能である疑い。これは私が3年前に出会ったコーディングの問題であり、今でも私はこれを自分で解決することはできません。
これまでの私のコード:(これは、ブルートフォースソリューションです)
#include <iostream>
using namespace std;
int main()
{
unsigned long long a, b;
cin >> a >> b;
for (unsigned long long x = 1; x < max(a, b); x++) {
unsigned long long c = a ^ x;
unsigned long long d = b + x;
if (c == d) {
cout << x << endl;
break;
return 0;
}
}
cout << -1; //if no such integer exists
return 0;
}
それは非常に難しいことではありません、あなただけの小さな考える必要があります。私たちが書いているとしA
、B
かつX
、バイナリにし、Aᵢ
右端の2に相当する値であるⁱビット。
我々はそれを知っています:Aₒ ⊕ Xₒ = Bₒ + Xₒ
。
= 15、B = 6は、バイナリに変換するA:レッツはそれを評価する方法を発見するために例を使用します。
A = 1 1 1 1 B = 0 1 1 0
X = a b c d X = a b c d
今、私たちはいくつかの可能性を持っています。のは、AとBの右端のビットを分析してみましょう:
1 ⊕ d = 0 + d
私たちは、それが知っているd
だけなので、0または1を指定できます。
for d = 0
1 ⊕ d = 0 + d => 1 ⊕ 0 = 0 + 0 => 1 = 0 (not possible)
for d = 1
1 ⊕ d = 0 + d => 1 ⊕ 1 = 0 + 1 => 0 = 1 (not possible)
これは、XORはちょうど(XORは、次のビット和のためのキャリーオーバーを作成していない点が異なる)のバイナリ合計のように振る舞うことを顕著です。
XOR SUM
0 ⊕ 0 = 0 | 0 + 0 = 0
0 ⊕ 1 = 1 | 0 + 1 = 1
1 ⊕ 0 = 1 | 1 + 0 = 1
1 ⊕ 1 = 0 | 1 + 1 = 0
満たすXを見つけることが常に可能ではありませんのでA ⊕ X = B + X
、そこではないため、値d
を満たすこと1 + d = 0 + d
。
Xが存在する場合はとにかく、あなただけ少しずつ見つけ、右から左に、この方法でそれを見つけることができます。
WORKING FULL例
= 15、B = 7:
A = 1 1 1 1 B = 0 1 1 1
X = a b c d X = a b c d
1 ⊕ d = 1 + d
ここで、D = 0とD = 1の両方が何その後、適用されますか?私たちは、次のビットをチェックする必要があります。仮定D = 1:
A = 1 1 1 1 B = 0 1 1 1
X = a b c d X = a b c d
1 ⊕ d = 1 + d => 1 ⊕ 1 = 1 + 1 => 0 = 0 (possible)
BUT 1 + 1 = 0 generates a carryover for the next bit sum:
Instead of 1 ⊕ c = 1 + c, we have 1 ⊕ c = 1 + c (+1) =
1 ⊕ c = c (not possible)
したがって、この場合には、dが0でなければなりません。
carryover 0
A = 1 1 1 1 B = 0 1 1 1
X = a b 0 0 X = a b 0 0
-----------------------------------
0 0
we know that c must be 0:
carryover 0 0
A = 1 1 1 1 B = 0 1 1 1
X = a b 0 0 X = a b 0 0
-----------------------------------
1 1 1 1
しかし、Bについて何?私たちはいつものように、次のビットをチェックする必要があります。
if b = 0, there won't be a carryover, so we'll have:
1 ⊕ a = 0 + a (and this is not possible)
so we try b = 1:
1 ⊕ b = 1 + b => 1 ⊕ 1 = 1 + 1 => 0 = 0 (with carryover)
そして今、のためにa
:
carryover 1 0 0
A = 1 1 1 1 B = 0 1 1 1
X = a 1 0 0 X = a 1 0 0
-----------------------------------
0 0 0 0 0 0
1 ⊕ a = 0 + a (+1) => 1 ⊕ a = 1 + a
ここではa
0と1にすることができますが、合計でキャリーオーバーを避けるために、0でなければなりませんB + X
。
その後、X = 0 1 0 0
、こうしてX = 4。
コード
#include <iostream>
using namespace std;
inline int bit(int a, int n) {
if(n > 31) return 0;
return (a & ( 1 << n )) >> n;
}
int main(){
int A = 19;
int B = 7;
int X = 0;
int carryover = 0;
int aCurrent, aNext, bCurrent, bNext;
for(int i = 0; i < 32; i++){
aCurrent = bit(A, i); bCurrent = bit(B, i);
aNext = bit(A, i + 1); bNext = bit(B, i + 1);
if(aCurrent == 0 && bCurrent == 0){
if(carryover) {X = -1; break;}
if(aNext != bNext){
X += 1 << i;
}
carryover = 0;
}
else if(aCurrent == 0 && bCurrent == 1){
if(!carryover) {X = -1; break;}
if(aNext == bNext){
X += 1 << i;
}
carryover = 1;
}
else if(aCurrent == 1 && bCurrent == 0){
if(!carryover) {X = -1; break;}
if(aNext != bNext){
X += 1 << i;
carryover = 1;
}
else {
carryover = 0;
}
}
else if(aCurrent == 1 && bCurrent == 1){
if(carryover) {X = -1; break;}
if(aNext != bNext){
X += 1 << i;
carryover = 1;
}
else {
carryover = 0;
}
}
}
if(X != -1) cout<<"X = "<<X<<endl;
else cout<<"X doesnt exist"<<endl;
return 0;
}
あなたは、テストすることができ、ここで。