CSES - E4590 2016 2 - Results
Submission details
Task:Fixed points
Sender:lippinj1
Submission time:2016-09-24 15:13:45 +0300
Language:C++
Status:READY
Result:
Test results
testverdicttime
#10.54 sdetails

Code

#include <iostream>
#include <string>
#include <vector>

bool nth_bit_of(unsigned long long val, int n)
{
    unsigned long long mask = (unsigned long long)(1) << n;
    return bool(mask & val);
}

unsigned long long prepend_nth(unsigned long long x, bool truthiness, int n)
{
    if (truthiness) {
        return x + ((unsigned long long)(1) << n);
    }
    else {
        return x;
    }
}

int find_C(unsigned long long a, unsigned long long x, int n)
{
    int sum = 0;
    for (int i = 1; i <= n; ++i) {
        if (nth_bit_of(a, i) == nth_bit_of(x, n - i)) sum++;
    }
    return sum;
}

void foo(bool a, bool b, bool C, bool& xFalseOk, bool& xTrueOk)
{
    xFalseOk = false;
    xTrueOk = false;

    if (a) {
        // 1 x x
        if (b) {
            // 1 1 x
            if (C) {
                // 1 1 1
                xFalseOk = true;
            }
        }
        else {
            // 1 0 x
            if (!C) {
                // 1 0 0
                xFalseOk = true;
                xTrueOk = true;
            }
        }
    }
    else {
        // 0 x x
        if (b) {
            // 0 1 x
            if (C) {
                // 0 1 1
                xFalseOk = true;
            }
            else {
                // 0 1 0
                xTrueOk = true;
            }
        }
        else {
            // 0 0 x
            if (C) {
                // 0 0 1
                xTrueOk = true;
            }
            else {
                // 0 0 0
                xFalseOk = true;
            }
        }
    }
}

unsigned long long find_fixed_point(unsigned long long a, unsigned long long b)
{
    struct Candidate {
        Candidate(unsigned long long p, int n, int c) : prefix(p), n(n), carry(c) {}

        unsigned long long prefix = 0;
        int n = 0;
        int carry = 0;
    };

    std::vector<Candidate> candidates;
    candidates.emplace_back(0, 0, 0);

    while (!candidates.empty()) {
        auto candidate = candidates.back();
        candidates.pop_back();

        auto x = candidate.prefix;
        auto n = candidate.n;

        if (((a * x) ^ b) == x) return x;
        if (n == 64) return 0;

        // std::cerr << "Trying to append bit " << n << " to " << x << std::endl;

        auto bit_a = nth_bit_of(a, 0);
        auto bit_b = nth_bit_of(b, n);

        auto C = candidate.carry + find_C(a, x, n);
        auto carry = C / 2;
        bool bit_C = C % 2;

        // std::cerr << "a: " << bit_a << " b: " << bit_b << " C: " << bit_C << std::endl;

        bool xFalseOk, xTrueOk;
        foo(bit_a, bit_b, bit_C, xFalseOk, xTrueOk);

        if (!xFalseOk && !xTrueOk) continue;

        if (xFalseOk) {
            // std::cerr << "0 bit OK" << std::endl;
            auto xx = prepend_nth(x, false, n);
            candidates.emplace_back(xx, n + 1, carry);
        }
        if (xTrueOk) {
            // std::cerr << "1 bit OK" << std::endl;
            auto xx = prepend_nth(x, true, n);
            candidates.emplace_back(xx, n + 1, carry + (bit_a ? 1 : 0));
        }
        // std::cerr << std::endl;
    }

    return 0;
}

int main()
{
    int t;
    std::cin >> t;


    std::vector<std::pair<unsigned long long, unsigned long long>> abs;
    for (int ti = 0; ti < t; ++ti) {
        unsigned long long a;
        unsigned long long b;
        std::cin >> a >> b;
        abs.push_back(std::make_pair(a, b));
    }

    for (const auto& ab : abs) {
        auto a = ab.first;
        auto b = ab.second;

        if (b == 0) {
            std::cout << "0" << std::endl;
        }
        else {
            auto ret = find_fixed_point(a, b);
            if (ret != 0) {
                std::cout << ret << std::endl;
            }
            else {
                std::cout << "-" << std::endl;
            }
        }
    }
}

Test details

Test 1

Verdict:

input
100000
12865169357617740396 294321893...

correct output
5903494652862419412
-
13008184152928659765
9415006529485574473
16201136572240455608
...

user output
-
-
-
-
-
...