Problem:
Score : 700 points

Problem Statement

Given is a sequence of N digits a_1a_2\ldots a_N, where each element is 1, 2, or 3.
Let x_{i,j} defined as follows:

x_{1,j} := a_j \quad (1 \leq j \leq N)

x_{i,j} := | x_{i-1,j} - x_{i-1,j+1} | \quad (2 \leq i \leq N and 1 \leq j \leq N+1-i)

Find x_{N,1}.

Constraints

2 \leq N \leq 10^6

a_i = 1,2,3 (1 \leq i \leq N)

Input

Input is given from Standard Input in the following format:

N
a_1a_2\ldotsa_N

Output

Print x_{N,1}.

Sample Input 1

4
1231

Sample Output 1

1

x_{1,1},x_{1,2},x_{1,3},x_{1,4} are respectively 1,2,3,1.

x_{2,1},x_{2,2},x_{2,3} are respectively |1-2| = 1,|2-3| = 1,|3-1| = 2.

x_{3,1},x_{3,2} are respectively |1-1| = 0,|1-2| = 1.

Finally, x_{4,1} = |0-1| = 1, so the answer is 1.

Sample Input 2

10
2311312312

Sample Output 2

0

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>

#define forn(i, n) for (int (i) = 0; (i) < (n); ++(i))

using ll=long long;
using ld=long double;
using pii = std::pair<int, int>;
#define x first
#define y second

template<typename T>
static inline T gcd(T a, T b) {
    a = std::abs(a);
    b = std::abs(b);
    while (b > 0) {
        a %= b;
        std::swap(a, b);
    }
    return a;
}

template<typename T>
static inline T gcm(T a, T b) {
    return a / gcd(a, b) * b;
}

template<typename T>
static inline T sqr(T a) {
    return a * a;
}

template<typename T>
static inline bool remin(T &a, const T &val) {
    if (a > val) {
        a = val;
        return true;
    }
    return false;
}

template<typename T>
static inline bool remax(T &a, const T &val) {
    if (a < val) {
        a = val;
        return true;
    }
    return false;
}

static inline ll nxt() {
    int64_t x;
    scanf("%" PRId64, &x);
    return x;
}

static inline void skipEndLine() {
    char c = getchar();
    while (c != '\n') {
        c = getchar();
    }
}

static inline std::string nxtLine() {
    std::string ret;
    char c = '\n';
    while (true) {
        c = getchar();
        if (c == '\n' || c == '\r' || c == -1) {
            break;
        }
        ret.push_back(c);
    }
    return ret;
}

static inline std::string nxtString() {
    std::string ret;
    char c = '\n';
    while (true) {
        c = getchar();
        if (!isspace(c)) {
            break;
        }
    }
    if (c == -1) {
        return ret;
    }
    ret.push_back(c);
    while (true) {
        c = getchar();
        if (isspace(c) || c == -1) {
            break;
        }
        ret.push_back(c);
    }
    return ret;
}

static std::chrono::system_clock::time_point clock_t0;

static inline void init_time() {
    clock_t0 = std::chrono::system_clock::now();
}

static inline double get_time() {
    auto t = std::chrono::system_clock::now();
    return std::chrono::duration<double>((t - clock_t0)).count();
}

static inline void print_time(const std::string &name) {
    std::cerr << name << " " << get_time() << "s." << std::endl;
}

template <class T>
static inline T pw(T a, ll n) {
    T ret = T(1);
    while (n > 0) {
        if (n & 1) ret = ret * a;
        a = a * a;
        n >>= 1;
    }
    return ret;
}

static inline ll pw(ll a, ll n, ll m) {
//    if (a == 0) return 0;
    a %= m;
    ll ret = 1;
    while (n > 0) {
        if (n & 1) ret = ret * a % m;
        a = a * a % m;
        n >>= 1;
    }
    return ret;
}

typedef std::thread thread_type;

class ThreadPool {
public:
    ThreadPool(size_t);

    template<class F, class... Args>
    auto enqueue(F &&f, Args &&... args)
    -> std::future<typename std::result_of<F(Args...)>::type>;

    ~ThreadPool();

private:
    // need to keep track of threads so we can join them
    std::vector<thread_type> workers;
    // the task queue
    std::queue<std::function<void()> > tasks;

    // synchronization
    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop;
};

// the constructor just launches some amount of workers
inline ThreadPool::ThreadPool(size_t threads)
        : stop(false) {
    for (size_t i = 0; i < threads; ++i) {
        auto f = [this] {
            for (;;) {
                std::function<void()> task;

                {
                    std::unique_lock<std::mutex> lock(this->queue_mutex);
                    this->condition.wait(lock,
                                         [this] { return this->stop || !this->tasks.empty(); });
                    if (this->stop && this->tasks.empty())
                        return;
                    task = std::move(this->tasks.front());
                    this->tasks.pop();
                }

                task();
            }
        };
        workers.emplace_back(f);
    }
}

// add new work item to the pool
template<class F, class... Args>
auto ThreadPool::enqueue(F &&f, Args &&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
    using return_type = typename std::result_of<F(Args...)>::type;

    auto task = std::make_shared<std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
    );

    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);

        // don't allow enqueueing after stopping the pool
        if (stop) {
            throw std::runtime_error("enqueue on stopped ThreadPool");
        }

        tasks.emplace([task]() { (*task)(); });
    }
    condition.notify_one();
    return res;
}

// the destructor joins all threads
inline ThreadPool::~ThreadPool() {
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        stop = true;
    }
    condition.notify_all();
    for (thread_type &worker: workers) {
        worker.join();
    }
}

static const ll ten9 = 1000 * 1000 * 1000;

template <class T>
struct Point2d {
    T x{0}, y{0};
    Point2d() = default;
    Point2d(T x, T y) : x(x), y(y) {}
    Point2d operator - (const Point2d &r) const {
        return Point2d(x - r.x, y - r.y);
    }
    Point2d operator + (const Point2d &r) const {
        return Point2d(x + r.x, y + r.y);
    }
    Point2d operator * (const T &r) const {
        return Point2d(x * r, y * r);
    }
    bool operator < (const Point2d &p) const {
        if (x != p.x) return x < p.x;
        return y < p.y;
    }
    bool operator <= (const Point2d &p) const {
        if (x != p.x) return x <= p.x;
        return y <= p.y;
    }
    bool operator == (const Point2d &p) const {
        return x == p.x && y == p.y;
    }
    bool operator != (const Point2d &p) const {
        return x != p.x || y != p.y;
    }
    bool operator > (const Point2d &p) const {
        if (x != p.x) return x > p.x;
        return y > p.y;
    }
    bool operator >= (const Point2d &p) const {
        if (x != p.x) return x >= p.x;
        return y >= p.y;
    }
    T sqlen() const {
        return x * x + y * y;
    }
    ld len() const {
        return sqrtl(sqlen());
    }
};

template <class T>
static inline T dot(const Point2d<T> &l, const Point2d<T> &r) {
    return l.x * r.x + l.y * r.y;
}

template <class T>
static inline T cross(const Point2d<T> &l, const Point2d<T> &r) {
    return l.x * r.y - l.y * r.x;
}


template <class T>
struct Fenwick {
    std::vector<T> t;

    inline void init(int n) {
        t.assign(n, T(0));
    }

    inline void inc(int p, T val) {
        for (;p < t.size(); p |= (p + 1)) {
            t[p] += val;
        }
    }

    inline T sum(int r) {
        T result = 0;
        for (; r >= 0; r &=(r+1), --r) {
            result += t[r];
        }
        return result;
    }

    inline T sum(int l, int r) {
        return sum(r) - sum(l-1);
    }

    inline void clear() {
        for (int &v : t) {
            v = T(0);
        }
    }
};

static const ld PI = acosl(-1.0);
static const ll mod = ten9 + 7;
using pt=Point2d<ll>;
using ptd = Point2d<ld>;
static std::mt19937_64 generator{123123};

using namespace std;

void prepare() {

}

int solve3(const string &a) {
    int q = 0;
    int n = a.size();
    for (int i = 0; i < n; ++i) {
        if ((i & (n - 1)) == i) {
            q ^= a[i];
        }
    }
    return q;
}

int solve2(const string &a) {
    if (a.size() == 1) return a[0];
    string b = a;
    for (char &x : b) {
        x &= 1;
    }
    if (solve3(b)) return 1;
    bool hasOne = false;
    for (int x : a) {
        if (x == 1) hasOne = true;
    }
    if (hasOne) {
        return 0;
    }
    b = a;
    for (char &x : b) {
        x /= 2;
    }
    if (solve3(b)) {
        return 2;
    }
    return 0;
}

int solve(const string &a) {
    if (a.size() == 1) return a[0];
    string b(a.size() - 1, 0);
    for (int i = 0; i < b.size(); ++i) {
        b[i] = abs(a[i] - a[i + 1]);
    }
    return solve2(b);
}

void solve() {
    int n = nxt();
    string s = nxtString();
    for (char &c : s) {
        c -= '0';
    }
    cout << solve(s) << "\n";
}

int main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    init_time();

    prepare();
    int t = 1;
//    t = nxt();
//    cin >> t;
    for (int i = 0; i < t; ++i) {
        solve();
    }

    print_time("Time:");
    return 0;
}