アルゴリズムは、XOR X = B + Xのための解決策を見つけること

AAaAa :

ように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;
}
ダニエル:

それは非常に難しいことではありません、あなただけの小さな考える必要があります。私たちが書いているとしABかつ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

ここではa0と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;
}

あなたは、テストすることができ、ここで

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=377026&siteId=1