import std.stdio, std.string, std.range, std.conv, std.array, std.algorithm, std.math, std.typecons;

void main() {
    const tmp = readln.split.to!(long[]);
    const A = tmp[0], B = tmp[1];

    // f(A,B) = AからBまでのすべての整数のxor
    // 各bitでもとめる
    // 1bit目はAからBまでのうち1のbitが奇数個なら1、偶数個なら0を返す
    // これは交互に来るから、結局(B-A+1)が奇数個かどうかで決まる
    // 2bit目はAからBまでのうち1のbitが奇数個なら1、偶数個なら0を返す
    // これは2個ずつ飛ばしで来るから、一般に
    // Nの2bit目が1であるとは、N%4が2か3であることを意味する
    // 一般にnbit目が1であるとは、N%(2^^n)が2^^(n-1)以上であることを意味する
    // 各桁を求めるにあたって、A%(2^^n) = a, B%(2^^n) = bであるとき、
    // aからはじめて2^^n個のセットは打ち消し合うので、結局そこ以降のxorをとればいい。

    long result;
    foreach (n; 1..64) {
        // A = (2^^n) * a + x
        // B = (2^^n) * b + y
        // C = (2^^n) * (a+1)
        // D = (2^^n) * b
        // [C,D)の区間には(D-C)/2個の1がある。
        // [A,C)の区間にはmax(2^^n-x, 2^^(n-1))個の1がある
        // [D,B]の区間にはmax(0, y-2^^(n-1)+1)個の1がある

        auto a = A / (1L << n);
        auto b = B / (1L << n);
        auto x = A % (1L << n);
        auto y = B % (1L << n);
        auto C = (1L << n) * (a+1L);
        auto D = (1L << n) * b;
        long cnt;
        cnt += (D-C)/2;
        cnt += min((1L << n)-x, (1L << (n-1L)));
        cnt += max(0, y-(1L << (n-1L))+1L);
        if (cnt % 2 == 1L) result |= (1L << (n-1L));
    }
    writeln(result);
}

