#pragma GCC optimize("O3")

#include <bits/stdc++.h>
using namespace std;
#define PII pair<int, int>
#define VI vector<int>
#define VPII vector<PII>
#define LL long long
#define LD long double
#define f first
#define s second
#define MP make_pair
#define PB push_back
#define endl '\n'
#define ALL(c) (c).begin(), (c).end()
#define SIZ(c) (int)(c).size()
#define REP(i, n) for(int i = 0; i < (int)(n); ++i)
#define FOR(i, b, e) for(int i = (b); i <= (int)(e); ++i)
#define FORD(i, b, e) for(int i = (b); i >= (int)(e); --i)

#define sim template<class n
sim, class s> ostream & operator << (ostream &p, pair<n, s> x)
{return p << "<" << x.f << ", " << x.s << ">";}
sim> auto operator << (ostream &p, n y) ->
typename enable_if<!is_same<n, string>::value, decltype(y.begin(), p)>::type 
{int o = 0; p << "{"; for(auto c: y) {if(o++) p << ", "; p << c;} return p << "}";}
void dor() {cerr << endl;}
sim, class...s> void dor(n p, s...y) {cerr << p << " "; dor(y...);}
sim, class s> void mini(n &p, s y) {if(p>y) p = y;}
sim, class s> void maxi(n &p, s y) {if(p<y) p = y;}
#ifdef DEB
#define debug(...) dor(__FUNCTION__, ":", __LINE__, ": ", __VA_ARGS__)
#else
#define debug(...)
#endif 

#define I(x) #x " =", (x), " "
#define A(a, i) #a "[" #i " =", i, "] =", a[i], " "


VI V2;
void iter(VI &V)
  {
  V2.clear();
  FOR(j, 1, (int)V.size()-1)
    {
    V2.PB(abs(V[j-1]-V[j]));
    }

  V = V2;
  }


VI good_simulate(VI V)
  {
  while(V.size() > 1)
    {
    iter(V);
    }
  return V;
  }


VI simulate(VI V)
  {
  while(V.size() > 1)
    {
    int pot = 1;
    while(pot * 2 < V.size())pot *= 2;
    VI nxt;
    // FOR(i, pot, V.size()-1)
    //   nxt.PB(abs(V[i] - V[i-pot]));

    FOR(i, pot, V.size()-1)
      nxt.PB(V[i] ^ V[i-pot]);
    V = nxt;
    }
  return V;
  }

VI simulate2(VI V)
  {
  while(V.size() > 1)
    {
    int pot = 1;
    while(pot * 2 < V.size())pot *= 2;
    VI nxt;
    // FOR(i, pot, V.size()-1)
    //   nxt.PB(abs(V[i] - V[i-pot]));

    int prev_1 = -1;
    REP(i, pot)if(V[i] == 1)prev_1 = i;

    FOR(i, pot, V.size()-1)
      {
      if(V[i] == 1)prev_1 = i;

      /*
      map<int, int> inside;
      FOR(j, i-pot+1, i-1)
        inside[V[j]]++;

      VI br;
      FOR(j, i-pot, i)
        br.PB(V[j]);
      int add = good_simulate(br)[0];

*/
      if(V[i] == 1 || V[i-pot] == 1)
        {
        nxt.PB(abs(V[i] - V[i-pot]));
//        assert(add == nxt.back());
        continue;
        }
      if(V[i] == 0 && V[i-pot] == 0)
        {
//        assert(add == 0);
        nxt.PB(0);

        continue;
        }

      if(V[i] == 2 && V[i-pot] == 2)
        {
//        assert(add == 0);
        nxt.PB(0);
        continue;
        }

      if(V[i] != V[i-pot])
        {
        int bede = (prev_1 < i-pot) * 2;
/*
        if(add != bede)
          {
          debug(br);
          debug(add, bede);
          assert(false);
          }*/

        nxt.PB(bede);
        continue;
        }


//      nxt.PB(add);
//      if(add)assert(inside[1] == 0);
      continue;

//      


      }
    V = nxt;
    }
  return V;
  }



int main()
{
  int n;
  scanf("%d", &n);
  VI V, Vpom;
  string s;
  int sum = 0;
  REP(i, n)
    {
    char a;
    scanf(" %c", &a);
    s += a;
    V.PB(a-'0');
    sum += a;
    
    }
  iter(V);
  debug(V);

  for(auto i: V)
    {
    if(i == 1)Vpom.PB(1);
    else Vpom.PB(0);
    }

  Vpom = simulate(Vpom);
  if(Vpom.back() == 1)
    {
    debug("TU");
    puts("1");
    return 0;
    }

  V = simulate2(V);
  printf("%d\n", V[0]);
  return 0;

//  Vpom.clear();
//  for(auto i: V)


  int mx = 0;
  while(V.size() > 1 && clock() < CLOCKS_PER_SEC * 1.95)
    {
    iter(V);
    mx = 0;
    for(auto i: V)maxi(mx, i);
    if(mx <= 1)break;
    }
  

  if(V.size() == 1)
    {
    printf("%d\n", V[0]);
    return 0;
    }
  if(mx <= 1)
    {
    printf("%d\n", simulate(V)[0]);
    return 0;
    }
//  while(1);

  printf("%d\n", 0);//mx == 2 ? 2 : 0);
  return 0;


  debug(s, V[0]);
  printf("%d\n", V[0] != 2 ? 0 : 2);
}


Measured memory_bytes: 21104