#include <cstdio>
#include <map>
#include <cassert>
using namespace std;
FILE *f, *g;
map <pair<pair<pair<pair<int, int>, int>, int>, int>, int>rez;
int k, x, y;
void readFile()
{
f = fopen("fractal.in", "r");
fscanf(f, "%d%d%d", &k, &y, &x);
fclose(f);
}
int rezz;
int getZona(int x1, int y1, int p2)
{
if(x1 > p2 && y1 > p2)
return 3;
if(x1 > p2 && y1 <= p2)
return 2;
if(x1 <= p2 && y1 > p2)
return 4;
if(x1 <= p2 && y1 <= p2)
return 1;
assert(1 == 0);
return 0;
}
const int l[] = {0, 0, 1, 1, 0};
const int c[] = {0, 0, 0, 1, 1};
void to1(int &l, int &c, int p2)
{
int aux = c;
c = p2 - l + 1;
l = aux;
}
void to4(int &l, int &c, int p2)
{
int aux = c;
c = l;
l = p2 - aux + 1;
}
int drum(int k, int x1, int y1, int x2, int y2);
int APEL =0 ;
struct vv
{
int x1, x2, y1, y2;
int k, z1,z2;
};
vv calc[10009];
int drumuri(int k, int x1, int y1, int x2, int y2, int z1, int z2)
{
calc[APEL + 1].x1 = x1;
calc[APEL + 1].x2 = x2;
calc[APEL + 1].y1 = y1;
calc[APEL + 1].y2 = y2;
calc[APEL + 1].k = k;
calc[APEL + 1].z1 = z1;
calc[APEL + 1].z2 = z2;
APEL ++;
int p2 = (1 << (k - 1));
int z3 = getZona(x1, y1, p2);
int z4 = getZona(x2, y2, p2);
assert(x1 > 0 && y1 > 0 && x2 > 0 && y2 > 0);
int pp = (1 << k)+1;
assert(x1 < pp && y1 < pp && x2 < pp && y2 < pp);
if(z1 != z3 || z2 != z4 || z3 > z4)
{
int eroare = 1;
while(eroare)
{
printf("ERROR!!!\n");
}
}
// printf("DRUMURI K=%d c1: %d %d c2: %d %d z: %d %d, %d %d\n", k, x1, y1, x2, y2, z1, z2, z3, z4);
if(rez[{{{{k, x1}, y1}, x2}, y2}] != 0)
return rez[{{{{k, x1}, y1}, x2}, y2}];
int ox1 = x1;
int ox2 = x2;
int oy1 = y1;
int oy2 = y2;
if(z1 == 2 && z2 == 3)
{
int midx1 = p2 + 1;
int midy1 = p2;
int midx2 = p2 + 1;
int midy2 = p2 + 1;
return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = 1 + drum(k - 1, x1 - p2, y1, midx1 - p2, midy1) + drum(k - 1, x2 - p2, y2 - p2, midx2 - p2, midy2 - p2);
}
if(z1 == 1 && z2 == 2)
{
int midx1 = p2;
int midy1 = 1;
int midx2 = p2 + 1;
int midy2 = 1;
to1(midx1, midy1, p2);
to1(x1, y1, p2);
// printf("DRUMURIIIIIIIII K=%d c1: %d %d c2: %d %d z: %d %d, \n", k, x1, y1, x2, y2, z1, z2);
return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = 1 + drum(k - 1, x1, y1, midx1, midy1) + drum(k - 1, x2 - p2, y2, midx2 - p2, midy2);
}
if(z1 == 3 && z2 == 4)
{
int midx1 = p2 + 1;
int midy1 = p2 * 2;
int midx2 = p2;
int midy2 = p2 * 2;///<< 1
to4(midx2, midy2, p2 * 2);
to4(x2, y2, p2 * 2);
return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = 1 + drum(k - 1, x1 - p2, y1 - p2, midx1 - p2, midy1 - p2) + drum(k - 1, x2, y2 /*- p2*/, midx2, midy2 /*- p2*/);
}
if(z1 == 1 && z2 == 4)
{
int midx1 = p2 + 1;
int midy1 = 1;
int midx2 = p2 * 2;
int midy2 = p2 * 2;
// printf("%d %d <= %d, %d\n", midx2, midy2,1 << k, getZona(midx2, midy2, p2));
return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = drumuri(k, x1, y1, midx1, midy1, 1,2) + drumuri(k, midx1, midy1, midx2, midy2, 2, 3) + drumuri(k, midx2, midy2, x2, y2, 3, 4);
}
if(z1 == 2 && z2 == 4)
{
int midx2 = p2 * 2;
int midy2 = p2 * 2;
return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = drumuri(k, x1, y1, midx2, midy2, 2, 3) + drumuri(k, midx2, midy2, x2, y2, 3, 4);
}
if(z1 == 1 && z2 == 3)
{
int midx1 = p2 + 1;
int midy1 = 1;
return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = drumuri(k, x1, y1, midx1, midy1, 1,2) + drumuri(k, midx1, midy1, x2, y2, 2, 3);
}
assert(1 == 0);
return 0;
}
void schimba(int &a, int &b)
{
int aux = a;
a = b;
b = aux;
}
int drum(int k, int x1, int y1, int x2, int y2)
{
// APEL++;
// printf("K=%d c1: %d %d c2: %d %d\n", k, x1, y1, x2, y2);
assert(x1 > 0 && y1 > 0 && x2 > 0 && y2 > 0);
int pp = (1 << k)+1;
assert(x1 < pp && y1 < pp && x2 < pp && y2 < pp);
if(x1 == x2 && y1 == y2){//printf("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO %d %d %d %d\n", x1, x2, y1, y2);
return 0;}
if(k == 1)
{
if(x1 == 1 && x2 == 1)
return 3;
if(x1 == 2 && x2 == 2)
return 1;
if(y1 == y2)
return 1;
return 2;
}
if(rez[{{{{k, x1}, y1}, x2}, y2}] != 0)
return rez[{{{{k, x1}, y1}, x2}, y2}];
int p2 = (1 << (k - 1));
int z1 = getZona(x1, y1, p2);
int z2 = getZona(x2, y2, p2);
// printf("+++++++++K=%d c1: %d %d c2: %d %d z: %d %d\n", k, x1, y1, x2, y2, z1, z2);
if(z1 > z2)
{
schimba(x1, x2);
schimba(y1, y2);
schimba(z1, z2);
}
// printf("+++++++++K=%d c1: %d %d c2: %d %d z: %d %d\n", k, x1, y1, x2, y2, z1, z2);
if(z1 == z2)
{
if(z1 == 2 || z1 == 3)
return rez[{{{{k, x1}, y1}, x2}, y2}] = drum(k - 1, x1 - p2 * l[z1], y1 - p2 * c[z1], x2 - p2 * l[z1], y2 - p2 * c[z1]);
else
{
if(z1 == 1)
{
to1(x1, y1, p2);
to1(x2, y2, p2);
}
if(z1 == 4)
{
to4(x1, y1, p2 * 2);
to4(x2, y2, p2 * 2);
}
return rez[{{{{k, x1}, y1}, x2}, y2}] = drum(k - 1, x1, y1, x2, y2);
}
}
return rez[{{{{k, x1}, y1}, x2}, y2}] = drumuri(k, x1, y1, x2, y2, z1, z2);
}
void solve()
{
rezz = drum(k, 1, 1, x, y);
/*printf("%d\n", APEL);
for(int i = 1; i <= APEL; i ++)
{
printf("DRUMURI K=%d c1: %d %d c2: %d %d z: %d %d = %d\n", calc[i].k, calc[i].x1, calc[i].y1, calc[i].x2, calc[i].y2, calc[i].z1, calc[i].z2, rez[{{{{calc[i].k, calc[i].x1}, calc[i].y1}, calc[i].x2}, calc[i].y2}]);
}*/
}
void printFile()
{
g = fopen("fractal.out", "w");
assert(rezz >= 0);
fprintf(g, "%d\n", rezz);
fclose(g);
}
int main()
{
readFile();
solve();
printFile();
return 0;
}